无法解开NSError

时间:2014-12-12 16:24:52

标签: ios swift mvvm optional nserror

对于这个问题,我使用的是实际代码的简化版本。

该应用程序使用MVVM架构构建。说那是一个登录屏幕。有3个文件。

ApiClient文件与服务器通信并获得响应。如果输入的用户名和密码匹配,则调用success闭包。匹配失败,我在NSError闭包中传递了自定义创建的failure对象。

ApiClient.swift

import Foundation

public class ApiClient {

    public func login(#username: String, password: String, success: (data: AnyObject!) -> Void, failure: (error: NSError) -> Void) {

        if username == "isuru" && password == "123" {
            let jsonResponse = "Login Successful"
            let data = jsonResponse.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)
            success(data: data!)
        } else {
            let userInfo = [
                NSLocalizedDescriptionKey: NSLocalizedString("Login Unsuccessful", comment: ""),
                NSLocalizedFailureReasonErrorKey: NSLocalizedString("Wrong Email or Password", comment: ""),
                NSLocalizedRecoverySuggestionErrorKey: NSLocalizedString("Please Try Again", comment: "")]
            let error = NSError(domain: "AppErrorDomain", code: 1200, userInfo: userInfo)
            failure(error: error)
        }
    }
}

LoginViewModel充当LoginViewControllerApiClient之间的中间人。

LoginViewModel.swift

import Foundation

protocol LoginDelegate {
    func loginCallFinished(status: Bool, error: NSError?)
}

class LoginViewModel {

    private let api = ApiClient()

    var delegate: LoginDelegate?

    init() { }

    func login(#username: String, password: String) {

        api.login(username: username, password: password, success: { (data) -> Void in
            if let delegate = self.delegate {
                delegate.loginCallFinished(true, error: nil)
            } else {
                fatalError("Have you set the LoginDelegate?")
            }
        }) { (error) -> Void in
            if let delegate = self.delegate {
                delegate.loginCallFinished(false, error: error)
            } else {
                fatalError("Have you set the LoginDelegate?")
            }
        }
    }
}

LoginViewController,我调用login()中的LoginViewModel功能。响应将返回到视图模型,并调用LoginDelegate函数loginCallFinished()并相应地传递参数值。

LoginViewController.swift

import UIKit

class LoginViewController: UIViewController, LoginDelegate {

    private let loginViewModel = LoginViewModel()

    override func viewDidLoad() {
        super.viewDidLoad()

        loginViewModel.delegate = self

        loginViewModel.login(username: "isuru", password: "12")
    }

    // MARK: - LoginDelegate
    func loginCallFinished(status: Bool, error: NSError?) {
        if status {
            println("Login Successful!")
        } else {
            if let error = error {
                let alert = UIAlertView(title: error.localizedDescription, message: "\(error.localizedFailureReason)\n\(error.localizedRecoverySuggestion)", delegate: nil, cancelButtonTitle: "OK")
                alert.show()
            }
        }
    }
}

逻辑正常。登录尝试失败时出现问题。假设我输入了错误的用户名或密码,它会返回我在login()文件的ApiClient函数中创建的自定义错误对象。我从LoginViewController检索它,并在UIAlertView

中显示错误
if let error = error {
    let alert = UIAlertView(title: error.localizedDescription, message: "\(error.localizedFailureReason)\n\(error.localizedRecoverySuggestion)", delegate: nil, cancelButtonTitle: "OK")
    alert.show()
}

但这就是我所看到的。

enter image description here

即使我打开error对象,我仍然会在字符串周围找到 Optional()括号。

任何人都知道为什么会这样?

谢谢。

1 个答案:

答案 0 :(得分:2)

您的error var已经解开了。问题是字符串error.localizedFailureReasonerror.localizedRecoverySuggestion未解包。为这些添加额外的if-let图层,或者通过这样的方式显式打开它们:

if let error = error {
    let alert = UIAlertView(title: error.localizedDescription, message: "\(error.localizedFailureReason!)\n\(error.localizedRecoverySuggestion!)", delegate: nil, cancelButtonTitle: "OK")
    alert.show()
}