我有一組拋出完成塊處理程式:
typealias CompletionBlock = (MyType) throws -> Void
private var handlers: [CompletionBlock] = []
我希望以后能夠召回它們并拋出如下錯誤:
for handler in handlers {
handler(throw myError)
}
但是,這不起作用,因為它希望我傳遞MyType給處理程式,而不是錯誤。我怎樣才能做到這一點?
uj5u.com熱心網友回復:
您的問題有點含糊,但我假設您的意思是您希望處理程式接受拋出函式的結果。這是可能的,我將展示如何,但這并不是你想要的。
“拋出函式的結果”可以通過呼叫呼叫拋出函式的函式來表示:
typealias CompletionBlock = (() throws -> MyType) -> Void
以您描述的方式拋出錯誤,如下所示:
let result: () throws -> MyType = { throw MyError() }
for handler in handlers {
handler(result)
}
處理程式將如下所示:
func h(result: () throws -> MyType) {
do {
let myType = try result()
// ...
} catch {
// ...
}
}
但這不是一個偉大的設計。最重要的是它執行result了很多次。相反,您想傳遞Result一個拋出函式:
typealias CompletionBlock = (Result<MyType, Error>) -> Void
let f: () throws -> MyType = { throw MyError() }
let result = Result(catching: f)
for handler in handlers {
handler(result)
}
更常見的外觀是這樣的:
let result = Result {
// Do various operations that might throw
return value
}
您還可以使用try result.get(). 因此,您可以輕松地在 Result 和 throws 之間隨意移動。結果最適合存盤。Throws 最適合呼叫。你可以兩者兼得。
(當然,您還應該展望未來并探索用 async/await 替換完成處理程式,但有很多原因您可能不會立即這樣做,因此 Result 將在相當長的一段時間內成為一個重要的工具。)
uj5u.com熱心網友回復:
您試圖通過強制它拋出錯誤來改變存盤閉包的行為,而不管其輸入如何。你不能這樣做。
CompletionBlock您標記為的事實throws僅意味著閉包本身可能會拋出。但是,您不能強制它拋出,因為您只能將型別的輸入引數傳遞MyType給它。
此外,強制關閉拋出是沒有意義的,因為無論如何您都需要處理從呼叫站點拋出的錯誤。所以你可以簡單地從呼叫站點拋出錯誤。
或者,如果您需要閉包本身來處理 a error,您應該將閉包更改為接受 a Result,并且.failure在注入的情況下,閉包本身可能會拋出。
typealias CompletionBlock = (Result<MyType, MyError>) throws -> Void
private var handlers: [CompletionBlock] = []
for handler in handlers {
handler(.failure(myError))
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/441316.html
