无法解开 NSError

Posted

技术标签:

【中文标题】无法解开 NSError【英文标题】:Cannot unwrap NSError 【发布时间】:2014-12-12 16:24:52 【问题描述】:

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

应用程序使用 MVVM 架构构建。假设有一个登录屏幕。有 3 个文件。

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

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,我调用LoginViewModel 中的login() 函数。响应返回给视图模型并调用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()
            
        
    

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

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

但这就是我看到的。

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

有人知道为什么会这样吗?

谢谢。

【问题讨论】:

【参考方案1】:

您的 error 变量已解包。问题是字符串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()

【讨论】:

是的,就是这样。谢谢。

以上是关于无法解开 NSError的主要内容,如果未能解决你的问题,请参考以下文章

无法转换类型的值'(数据:CMAccelerometerData!,错误:NSError!)

无法使用类型为 (('WeatherResponse?, NSError?) -> Void 的参数列表调用“responseObject”

在 Swift 3 中无法转换 (NSError)-> Void

无法将类型“([AnyObject]!,NSError!)-> Void”的值转换为期望参数类型“CLGeocodeCompletionHandler”

无法将类型 (PFUser!, NSError) void 的值转换为预期的参数类型 PFUserResultBlock

无法将“NSError”(0x264bd90)类型的值转换为“NSString”