비탈출 매개변수를 폐쇄적으로 사용하면 탈출할 수 있습니다.
프로토콜이 있습니다.
enum DataFetchResult {
case success(data: Data)
case failure
}
protocol DataServiceType {
func fetchData(location: String, completion: (DataFetchResult) -> (Void))
func cachedData(location: String) -> Data?
}
구현 예를 사용하여:
/// An implementation of DataServiceType protocol returning predefined results using arbitrary queue for asynchronyous mechanisms.
/// Dedicated to be used in various tests (Unit Tests).
class DataMockService: DataServiceType {
var result : DataFetchResult
var async : Bool = true
var queue : DispatchQueue = DispatchQueue.global(qos: .background)
var cachedData : Data? = nil
init(result : DataFetchResult) {
self.result = result
}
func cachedData(location: String) -> Data? {
switch self.result {
case .success(let data):
return data
default:
return nil
}
}
func fetchData(location: String, completion: (DataFetchResult) -> (Void)) {
// Returning result on arbitrary queue should be tested,
// so we can check if client can work with any (even worse) implementation:
if async == true {
queue.async { [weak self ] in
guard let weakSelf = self else { return }
// This line produces compiler error:
// "Closure use of non-escaping parameter 'completion' may allow it to escape"
completion(weakSelf.result)
}
} else {
completion(self.result)
}
}
}
위의 코드는 Swift3(Xcode8-beta5)에서 컴파일되어 작동했지만 베타 6에서는 더 이상 작동하지 않습니다.근본적인 원인을 말씀해 주시겠습니까?
이는 함수 유형의 매개 변수에 대한 기본 동작이 변경되었기 때문입니다.Swift 3(특히 Xcode 8 베타 6과 함께 제공되는 빌드) 이전에는 기본적으로 이스케이프 상태가 됩니다. 이를 표시해야 합니다.@noescape
저장되거나 캡처되는 것을 방지하기 위해 기능 호출 기간보다 오래 지속되지 않도록 보장합니다.
하지만, 지금은@noescape
는 함수 계산 매개 변수의 기본값입니다.이러한 기능을 저장하거나 캡처하려면 이제 해당 기능을 표시해야 합니다.@escaping
:
protocol DataServiceType {
func fetchData(location: String, completion: @escaping (DataFetchResult) -> Void)
func cachedData(location: String) -> Data?
}
func fetchData(location: String, completion: @escaping (DataFetchResult) -> Void) {
// ...
}
이 변경에 대한 자세한 내용은 Swift Evolution 제안서를 참조하십시오.
@noescape가 기본이므로 오류를 수정하는 두 가지 옵션이 있습니다.
@Hamish가 그의 대답에서 지적했듯이, 만약 당신이 결과에 관심이 있고 정말로 그것이 탈출하기를 원한다면, 단지 완료를 @escape로 표시하세요 (그것은 아마도 유닛 테스트와 비동기 완료의 가능성을 가진 @Lukasz의 질문의 경우일 것입니다).
func fetchData(location: String, completion: @escaping (DataFetchResult) -> Void)
OR
결과에 관심이 없는 경우 완료 옵션을 선택하여 결과를 모두 삭제함으로써 기본 @noescape 동작을 유지합니다.예를 들어 사용자가 이미 "떠났"고 콜링 뷰 컨트롤러가 부주의한 네트워크 호출이 있었다고 해서 메모리에 남아 있을 필요가 없는 경우입니다.제가 답을 찾으러 왔을 때와 마찬가지로 샘플 코드는 저와 별로 관련이 없었기 때문에 @noescape를 표시하는 것은 처음에는 유일한 것처럼 들렸지만 최선의 선택은 아니었습니다.
func fetchData(location: String, completion: ((DataFetchResult) -> Void)?) {
...
completion?(self.result)
}
완료 블록 만들기:optional
변수는 스위프트 5의 문제를 해결하는 데 도움이 되었습니다.
private func updateBreakTime(for id: String, to time: Time, onSucess: EmptyAction?) {
dataRepository.updateBreak(
id: id,
to: time.seconds,
onSuccess: { _ in
onSucess?()
},
onError: { [weak self] error in
self?.screen.showError(error)
}
)
}
데이터 저장소의 성공 여부@escaping
언급URL : https://stackoverflow.com/questions/38990882/closure-use-of-non-escaping-parameter-may-allow-it-to-escape
'code' 카테고리의 다른 글
C에서 #error 지시어의 용도는 무엇입니까? (0) | 2023.06.17 |
---|---|
인쇄 출력의 10진수(R) 수 제어 (0) | 2023.06.17 |
$.textstatus는 성공을 표시하지만 데이터베이스는 업데이트되지 않습니까?제이쿼리 php 아약스 (0) | 2023.06.17 |
adplyrtbl 열을 벡터로 추출합니다. (0) | 2023.06.17 |
Oracle 사용자 계정 상태를 EXPIRE(GRACE)에서 OPEN으로 변경 (0) | 2023.06.17 |