是否可以使用带有swift 2的do / catch块来捕获错误“致命错误:在展开可选值时意外发现nil”?

时间:2016-02-29 21:48:57

标签: swift2

示例代码:

if let result = Locksmith.loadDataForUserAccount("UserAccount") {
  do {
    account = Account(
      id: result["id"] as! String,
      uid: result["uid"] as! String,
      username: result["username"] as! String,
      name: result["name"] as! String,
      image: result["image"] as! String,
      token: result["token"] as! String,
      client: result["client"] as! String
    )
  } catch _ {
    // Xcode show this warning:
    // 'catch' block is unreachable because no errors are thrown in 'do' block
  }
}

任何结果的键都可以是nil。

有没有办法只是抓住错误,如果其中任何一个 nil

1 个答案:

答案 0 :(得分:5)

你不能那样做,因为nil值的强制解包确实生成fatal_error(这不像抛出ErrorType)。

Failable Initializer

但是,只需将failable initializer添加到Account即可解决您的问题(如果它是struct则会更容易。)

struct Account {
    let id: String
    let uid: String
    let username: String
    let name: String
    let image: String
    let token: String
    let client: String

    init?(dict:[String:Any]) {
        guard let
            id = dict["id"] as? String,
            uid = dict["uid"] as? String,
            username = dict["username"] as? String,
            name = dict["name"] as? String,
            image = dict["image"] as? String,
            token = dict["token"] as? String,
            client = dict["client"] as? String else { return nil }
        self.id = id
        self.uid = uid
        self.username = username
        self.name = name
        self.image = image
        self.token = token
        self.client = client
    }
}

现在

if let
    result = Locksmith.loadDataForUserAccount("UserAccount"),
    account = Account(dict:result) {
    // use account here
}

投掷初始化程序

如果知道某些字段缺失对您来说还不够,并且您需要知道哪个是停止初始化Account的第一个缺失字段,则可以定义一个抛出初始化程序。

首先,您需要一种表示错误的方法

enum AppError: ErrorType {
    case MissingField(String)
}

下一步

struct Account {
    let id: String
    let uid: String
    let username: String
    let name: String
    let image: String
    let token: String
    let client: String

    init(dict:[String:Any]) throws {
        guard let id = dict["id"] as? String else { throw AppError.MissingField("id") }
        guard let uid = dict["uid"] as? String  else { throw AppError.MissingField("uid") }
        guard let username = dict["username"] as? String else { throw AppError.MissingField("username") }
        guard let name = dict["name"] as? String else { throw AppError.MissingField("name") }
        guard let image = dict["image"] as? String else { throw AppError.MissingField("image") }
        guard let token = dict["token"] as? String else { throw AppError.MissingField("token") }
        guard let client = dict["client"] as? String else { throw AppError.MissingField("client") }

        self.id = id
        self.uid = uid
        self.username = username
        self.name = name
        self.image = image
        self.token = token
        self.client = client
    }
}

让我们看看它是如何运作的

do {
    let dict:[String:Any] = ["id": "1", "uid": "1234"]
    let account = try Account(dict: dict)
} catch let appError {
    print(appError)
}

输出

  

MissingField("用户名&#34)