致命错误:在解包一个可选值Swift时意外地发现了nil

时间:2016-03-01 12:04:18

标签: json swift nsdictionary

所以我现在正在尝试将存储在NSUserdefault中的NSDictionary转换为用于表内容的数组,但是我遇到了许多错误,包括“致命错误:在展开可选值时意外发现nil”,(当前一个) 只是想知道什么是最安全和正确的转换方式。

这是我的代码。

        let nsd:NSDictionary = NSUserDefaults.standardUserDefaults().valueForKey("storedPosts") as! NSDictionary
        for (postId, postInfo) in nsd{ //post id and the post
            let importedPost:Post = Post(postId: postId as! String, priorityLevel: postInfo.objectForKey("priorityLevel") as! String, status: postInfo.objectForKey("status") as! String, section: postInfo.objectForKey("section") as! String, userType: postInfo.objectForKey("userType") as! String, dataPosted: postInfo.objectForKey("dataPosted") as! String, lastUpdate: postInfo.objectForKey("lastUpdate") as! String, states: postInfo.objectForKey("states") as! String, personalizedToViewerData: postInfo.objectForKey("personalizedToViewerData") as! [String:Bool], content: postInfo.objectForKey("content") as! Dictionary<String, Any>)
        posts.append(importedPost)
}

任何建议都会受到赞赏

1 个答案:

答案 0 :(得分:1)

当你用!“强制解包”一个Optional时,你告诉编译器“我们可以随时解包,因为我知道肯定会有值”。

但如果实际上没有价值,应用程序将崩溃......

所以你必须先安全打开你的选项。

有很多技巧,现在最简单的是if let

使用“if let”可以安全地将值解包为新常量,然后可以使用此新常量而不是Optional。如果您需要检查类型或向下转发,您可以使用if let xxx = yyy as? zzz使用“条件向下转换”(我相信真实姓名是“可选绑定”)。

让我们看看我们如何做到这一点:

if let nsd = NSUserDefaults.standardUserDefaults().valueForKey("storedPosts") as? NSDictionary {
    // use `nsd` here
}

让我们走得更远:

if let nsd = NSUserDefaults.standardUserDefaults().valueForKey("storedPosts") as? NSDictionary {
    for (postId, postInfo) in nsd {
        if let id = postId as? String {

        }
    }
}

它有效,但我们看到每个值使用“if let”会导致“厄运金字塔”......

一个经典的解决方案是使用多个可选绑定,使用相同的“if let”:

if let nsd = NSUserDefaults.standardUserDefaults().valueForKey("storedPosts") as? NSDictionary {
    for (postId, postInfo) in nsd {
        if let id = postId as? String,
            priorityLevel = postInfo.objectForKey("priorityLevel") as? String,
            status = postInfo.objectForKey("status") as? String,
            section = postInfo.objectForKey("section") as? String {  // keep doing the same for all your values

            let importedPost = Post(postId: id, priorityLevel: priorityLevel, status: status, section: section, ...)  // etc

        }
    }
}

一个很好的副作用是你现在可以通过在需要它的“if let”条件中添加else分支来处理错误。