2017-07-02 39 views
0

我想做一個很好的方式來處理錯誤使用UIAlertController與重試導致錯誤的代碼選項。我想出了,不知怎的,實際工作這個巨大的混亂:Swift:錯誤處理與拋出逃脫封閉(令人困惑)

func handleError(_ closure: @escaping() throws -> Void) { 
    do { 
    try closure() 
    } catch { 
    print(error) 
    let alert = UIAlertController(title: "Error", message: error.localizedDescription, preferredStyle: .alert) 
    let retry = UIAlertAction(title: "Retry", style: .default, handler: {(_: UIAlertAction) in self.handleError(closure)}) 
    alert.addAction(retry) 
    let cancel = UIAlertAction(title: "Cancel", style: .cancel) 
    alert.addAction(cancel) 
    present(alert, animated: true) 
    } 
} 

然而,只看這個,好像它會造成比阻止他們更多的錯誤。有什麼我可以做的,使這個簡單或更少混淆?我無法理解爲什麼我需要@escaping部分(但編譯器告訴我我),或者爲什麼我需要爲UIAlertAction關閉提供一個空白參數。

我只需要一些保證,這不是一個解決方案太糟糕。

回答

1

@escaping的想法讓你意識到你的閉包將在異步調用中執行。這樣想:假設你必須調用一個你自己沒有開發的函數,並且必須通過一個閉包。現在假設你期望閉包將作爲同步調用來執行。你怎麼知道它是否只能用作同步呼叫? Swift使用@escaping註釋給你這個保證。如果該函數用於任何異步調用,則必須在函數簽名中通知該函數。在你的情況下,你將函數傳遞給AlertController,它將等待用戶操作調用閉包。

而關於空白參數,實際上這不是一個空白參數,它是一個函數簽名。在這裏你告訴編譯器你會收到一個函數作爲參數,而且這個函數沒有參數並且什麼都不返回,但是可以拋出一個異常。在迅捷中,函數有類型。接收字符串作爲參數並返回布爾值的函數的類型爲(String)-> Bool。使用空參數,您可以定義您將接受的函數類型作爲參數,在這種情況下,您的函數類型爲() ->(),可以概括爲(),意思是:一個沒有參數且不返回任何內容的函數。

你可以在swift here找到更多關於函數類型的信息。

順便說一句,我認爲你的代碼是正確的。我沒有看到任何問題,但爲了給你一個適當的迴應,我必須知道你的結局會是什麼。

+0

閉包可以是需要在其前面「嘗試」工作的任何代碼。我想在各種地方使用它 – MysteryPancake

+0

與嘗試和關閉沒有任何關係。在調用任何可能拋出異常的函數之前,您必須使用try。如果一個操作可以拋出一個異常(認爲是一個受控的錯誤),你必須使用try。閉包是一種特殊類型的函數,您可以將其作爲參數傳遞給其他函數。 –

+0

我可以簡化這段代碼的任何部分嗎?我主要考慮(_:UIAlertAction)部分 – MysteryPancake