주어진:
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
있습니까?
유형을 변경하면 다음 오류가 발생합니다.
@escaping 속성은 함수 유형에만 적용됩니다
@escaping
속성을 제거하면 코드가 컴파일되고 실행되지만 completion
클로저가 함수의 범위를 벗어나 므로 올바른 것으로 보이지 않습니다 .
답변
가 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으로 유지하는@escaping
선택적 함수 유형에서 속성을 제거하는 것입니다 .
func doStuff(stuff: String, completion: Action?) {...}
편집 2 : :
SR-2444은 매개 변수의 위치에 폐쇄가 있음을 명시 적으로 진술 폐쇄되어 있지 탈출하고 표시 할 필요할 @escaping
선택적 매개 변수 그들을 탈출하기 위해,하지만 되어 있기 때문에, 암시 탈출 ((Int)->())?
의 동의어이며 Optional<(Int)->()>
, 임의 폐쇄 탈출한다.
답변
보낸 사람 : swift-users 메일 링리스트
기본적으로 @escaping은 함수 매개 변수 위치의 클로저에서만 유효합니다. 기본적으로 noescape 규칙은 함수 매개 변수 위치에서 이러한 클로저에만 적용되며, 그렇지 않으면 이스케이프됩니다. 값이 연관된 열거 형 (예 : 선택 사항), 튜플, 구조체 등의 집계와 같이 집계가있는 집계는 함수 매개 변수 위치에 있지 않은 (즉, 탈출하는) 클로저에 대한 기본 규칙을 따릅니다.
따라서 선택적 함수 매개 변수는 기본적으로 @escaping입니다.
@noeascape는 기본적으로 함수 매개 변수에만 적용됩니다.
답변
혼합 @escaping
과 비가 @escaping
혼동 되기 때문에 비슷한 문제가 발생했습니다 . 특히 클로저를 통과 해야하는 경우 특히 그렇습니다.
나는 via 매개 변수에 no-op 기본값을 지정하여 via를 통해 종료했습니다 = { _ 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?()
}
답변
예제에서 이해해야 할 중요한 사항 은 클로저 로 변경 Action
하면 탈출하는 것입니다. 제안하는 것을 해보자.Action?
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
}
}
}
글쎄, 그 요구 사항은 폐쇄를 탈출하는 경우에만 발생합니다. 따라서 폐쇄는 탈출하고 있습니다. 따라서 이스케이프 표시 하지 않는 이유는 이미 이스케이프 처리 중입니다.