programing

신속한 선택적 이스케이프 클로저 매개변수

mailnote 2023. 5. 31. 18:23
반응형

신속한 선택적 이스케이프 클로저 매개변수

주어진:

typealias Action = () -> ()

var action: Action = { }

func doStuff(stuff: String, completion: @escaping Action) {
    print(stuff)
    action = completion
    completion()
}

func doStuffAgain() {
    print("again")
    action()
}

doStuff(stuff: "do stuff") { 
    print("swift 3!")
}

doStuffAgain()

그것을 만들 방법이 있습니까?completion매개 변수(및)action) 유형의Action?그리고 또한.@escaping?

유형을 변경하면 다음 오류가 발생합니다.

@filename 특성은 함수 유형에만 적용됩니다.

제거@escaping속성, 코드는 컴파일되고 실행되지만, 이후로 정확하지 않은 것 같습니다.completion폐쇄는 함수의 범위를 벗어나는 것입니다.

보낸 사람: 빠른 사용자 메일링 목록

기본적으로 @escape는 함수 매개변수 위치의 폐쇄에서만 유효합니다.기본적으로 noescape by default 규칙은 함수 매개 변수 위치에 있는 이러한 폐쇄에만 적용되며, 그렇지 않으면 이 폐쇄가 해제됩니다.관련 값(예: 옵션)이 있는 열거형, 튜플, 구조체 등과 같은 집합체는 폐쇄가 있는 경우 함수 매개변수 위치에 있지 않은 폐쇄에 대한 기본 규칙, 즉 탈출합니다.

따라서 선택적 함수 매개변수는 기본적으로 @escape입니다.
@noeascape는 기본적으로 함수 매개 변수에만 적용됩니다.

SR-2552에서 다음과 같이 보고되었습니다.@escaping함수 유형 별칭을 인식하지 못합니다.그것이 오류가 발생한 이유입니다.@escaping attribute only applies to function types함수 서명에서 함수 유형을 확장하여 해결할 수 있습니다.

typealias Action = () -> ()

var action: Action? = { }

func doStuff(stuff: String, completion: (@escaping ()->())?) {
    print(stuff)
    action = completion
    completion?()
}

func doStuffAgain() {
    print("again")
    action?()
}

doStuff(stuff: "do stuff") {
    print("swift 3!")
}

doStuffAgain()

편집 1:

저는 사실 아직 버그 SR-2552가 해결되지 않은 xcode 8 베타 버전을 받고 있었습니다. 그 버그를 수정하고, 여전히 열려 있는 새로운 버그를 소개했습니다.SR-2444를 참조하십시오.

@Michael Ilseman이 임시 해결책으로 지적한 해결책은 제거하는 것입니다.@escaping선택적 함수 유형의 속성으로, 함수를 이스케이프로 유지합니다.

func doStuff(stuff: String, completion: Action?) {...}

편집 2:

SR-2444매개변수 위치의 폐쇄가 빠져나가지 않으며 다음과 같이 표시해야 함을 명시적으로 명시하여 폐쇄되었습니다.@escaping탈출하게 만들지만 선택적 매개 변수는 암시적으로 탈출합니다.((Int)->())?의 동의어입니다.Optional<(Int)->()>선택적 폐쇄가 탈출하고 있습니다.

저도 비슷한 문제에 부딪혔어요. 왜냐하면 섞기 때문입니다.@escaping및 비@escaping특히 폐쇄를 전달해야 할 경우 매우 혼란스럽습니다.

나는 결국 다음을 통해 폐쇄 매개 변수에 no-op 기본값을 할당했습니다.= { _ in }그게 더 말이 되는 것 같아요

func doStuff(stuff: String = "do stuff",
        completion: @escaping (_ some: String) -> Void = { _ in }) {
     completion(stuff)
}

doStuff(stuff: "bla") {
    stuff in
    print(stuff)
}

doStuff() {
    stuff in
    print(stuff)
}

저는 Swift 3에서 아무런 경고 없이 오직 이런 식으로만 작동하게 되었습니다.

func doStuff(stuff: String, completion: (()->())? ) {
    print(stuff)
    action = completion
    completion?()
}

이 예에서 이해해야 할 중요한 것은 만약 당신이 변화한다면ActionAction?폐쇄가 빠져나가고 있습니다.제안하신 대로 하겠습니다.

typealias Action = () -> ()

var action: Action? = { }

func doStuff(stuff: String, completion: Action?) {
    print(stuff)
    action = completion
    completion?()
}

좋아요, 이제 전화할게요doStuff:

class ViewController: UIViewController {
    var prop = ""
    override func viewDidLoad() {
        super.viewDidLoad()
        doStuff(stuff: "do stuff") {
            print("swift 3!")
            print(prop) // error: Reference to property 'prop' in closure 
                        // requires explicit 'self.' to make capture semantics explicit
        }
    }
}

그 요구사항은 폐쇄를 탈출하는 경우에만 발생합니다.그래서 폐쇄가 빠져나가고 있습니다.그래서 탈출이라고 표시하지 않는 거죠. 이미 탈출하고 있어요.

언급URL : https://stackoverflow.com/questions/39618803/swift-optional-escaping-closure-parameter

반응형