오류를 좋은 느낌으로 UIAlertController로 표시

iOS에서 오류가 발생하면 UIAlertController에 표시하는 것은 드물지 않지만 그때 발생하는 오류를 바탕으로 좋은 느낌으로 UialertController에 표시합니다.

"좋은 느낌"의 정의



「좋은 느낌」의 정의로서는, macOS에서 사용되고 있는 AppKit의 NSAlert 를 참고로 합니다.
NSAlert라는 것은 이런 느낌의 녀석입니다.


NSAlert안에는 messageText , informativeText 가 표시되어 버튼이 존재합니다.
대체로 UialertController title , message 와 같은 형태로 보이지 않습니까?

NSAlert에는 Error를 건네주어 생성하는 것으로, 이러한 요소가 자동으로 붙기 때문에, 마찬가지로 UIAlertController에서도, Error를 건네주는 것만으로 각종 파라미터가 설정되도록 합니다.

UIAlertController 표시



NSAlert messageText 는 NSError localizedDescription , informativeText 에는 NSError localizedRecoverySuggestion 가 사용되고 있습니다. 따라서 Error를 NSError로 캐스트하여 이러한 매개 변수를 할당하면 OK입니다.
        let nsError = error as NSError
        let alert = UIAlertController(title: nsError.localizedDescription,
                                      message: nsError.localizedRecoverySuggestion,
                                      preferredStyle: .alert)

LocalizedError 생성



실제로 NSError의 매개 변수를 알았을 때 생성 된 오류가이 사양을 준수하지 않으면 의미가 없으므로이 사양을 준수하는 오류를 생성합니다.

NSError를 생성하고 NSLocalizedDescriptionKey 등을 UserInfo로 설정하는 것도 좋지만 Swift이면 LocalizedError
LocalizedError에 포함된 errorDescription 는 NSError로 캐스트할 때 localizedDescription , recoverySuggestionlocalizedRecoverySuggestion .
enum MyError: LocalizedError {
    case error1

    var errorDescription: String? { return "errorDescription" }
    var recoverySuggestion: String? { return "recoverySuggestion" }
}

RecoverableError로 복구 가능



NSAlert에 RecoverableError 에 적합한 에러를 건네주어 생성하면, 복구 옵션 버튼이 붙은 NSAllert를 생성할 수 있습니다.
이러한 버튼을 누르면 RecoverableError내에서 구현한 복구 처리가 움직이므로, 이쪽도 UialertController에 재현해 봅시다.

이전 LocalizedError를 포함하여 macOS presentError와 같이 UIViewController 클래스에서 오류를 표시 할 수있는 extension을 만들려고했습니다.delegate 또는 didRecoverSelector 를 설정하여 복구 시 return을 얻을 수 있습니다.
extension UIViewController {
    func presentError(_ error: Error,
                      delegate:Any? = nil,
                      didRecoverSelector:Selector? = nil,
                      contextInfo: UnsafeMutableRawPointer? = nil) {
        let nsError = error as NSError
        let alert = UIAlertController(title: nsError.localizedDescription,
                                      message: nsError.localizedRecoverySuggestion,
                                      preferredStyle: .alert)

        if let localizedRecoveryOptions = nsError.localizedRecoveryOptions,
            !localizedRecoveryOptions.isEmpty,
            let attempter: AnyObject = nsError.recoveryAttempter as AnyObject? {

            for (i, value) in localizedRecoveryOptions.enumerated() {
                let alertAction = UIAlertAction(title: value, style: .default) { _ in
                    attempter.attemptRecovery(fromError: error,
                                              optionIndex: i,
                                              delegate: delegate,
                                              didRecoverSelector: didRecoverSelector,
                                              contextInfo: contextInfo)
                }
                alert.addAction(alertAction)
            }
        } else {
            alert.addAction(UIAlertAction(title: NSLocalizedString("ok", value: "OK", comment: "エラーアラートのデフォルトボタン"), style: .default, handler: nil))
        }
        present(alert, animated: true, completion: nil)
    }
}

추가: presentError 사용법


class ViewController: UIViewController {

    @IBAction func showError(_ sender: Any) {
        presentError(MyLocalizedError.error1)
    }

    @IBAction func showRecoverableError(_ sender: Any) {
        // リカバリー付きエラーを表示
        presentError(MyRecoverableError.error1, delegate: self, didRecoverSelector: #selector(didPresentErrorWithRecovery(_:contextInfo:)), contextInfo: nil)
    }

    /// リカバリーの結果が返ってくる
    /// - Parameters:
    ///   - didRecover: attemptRecoveryの成功有無
    ///   - contextInfo: エラー回復の試行に関連する任意のデータ
    @objc func didPresentErrorWithRecovery(_ didRecover:Bool, contextInfo:UnsafeMutableRawPointer?) {
    }
}

비교해보자





macOS
iOS


오류



LocalizedError



LocalizedError & RecoverableError




요약



잡자! LocalizedError!

좋은 웹페이지 즐겨찾기