【问题标题】:fatal error: unexpectedly found nil while unwrapping an Optional value, Swift致命错误:在展开可选值时意外发现 nil,Swift
【发布时间】:2016-03-01 12:04:18
【问题描述】:

所以我现在正在尝试将存储在 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)
}

任何建议都将不胜感激

【问题讨论】:

  • 首先你需要绝对停止使用!的强制展开和强制向下转换,你必须确保一切安全,例如if let ... = ... else ...,这样你可以处理可能的错误。如果仍有问题,我们会提供帮助。
  • 如果您遇到问题 - 不要将所有代码都放在一行中 - 将其拆分为块,这样调试起来会容易得多
  • @EricD。感谢您的及时回复,我会更改并编辑帖子
  • @Russell Yeap,我会跟随 Eirc 的领导,看看我是否能解决问题
  • 使用条件向下转换,例如:if let id = postId as? String {。如果你愿意,你甚至可以在同一行上做多个:if let id = postId as? String, info = postInfo.objectForKey("priorityLevel") as? String { 等等。

标签: json swift nsdictionary


【解决方案1】:

当你用!“强制解包”一个 Optional 时,你是在告诉编译器“没关系,我们总是可以解包,因为我确信总会有一个值”。

但如果真的没有价值,应用就会崩溃……

所以你必须首先安全地打开你的 Optionals。

有很多技巧,目前最简单的是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

        }
    }
}

一个不错的副作用是,您现在可以通过将else 分支添加到需要它的“if let”条件来处理错误。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-11-30
    • 2015-03-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多