【问题标题】:fatal error: Can't unwrap Optional.None When using Swift with Parse致命错误:使用 Swift 和 Parse 时无法打开 Optional.None
【发布时间】:2014-11-22 12:40:51
【问题描述】:

我已经按照这个将您的 swift 应用程序连接到 Parse.com 教程:http://ios-blog.co.uk/tutorials/connect-your-swift-application-to-parse-com/ 并且效果很好。本教程仅向您展示如何在 Parse.com 服务上放置数据。所以我对如何检索数据进行了一些研究。

在第一个教程中,它说要像这样向 Parse 添加数据:

    Parse.setApplicationId("your_application_key", clientKey: "your_client_key")

    var object = PFObject(className: "testDataClass")
    object.addObject("iOSBlog", forKey: "websiteUrl")
    object.addObject("Five", forKey: "websiteRating")
    object.save()

Parse 团队 (http://blog.parse.com/2014/06/06/building-apps-with-parse-and-swift/) 编写的第二个教程中说要这样写:

var gameScore = PFObject(className: "GameScore")
gameScore.setObject(1337, forKey: "score")
gameScore.setObject("Sean Plott", forKey: "playerName")
gameScore.saveInBackgroundWithBlock { 
    (success: Bool!, error: NSError!) -> Void in
    if success {
        NSLog("Object created with id: \(gameScore.objectId)")
    } else {
        NSLog("%@", error)
    }
}

然后要检索它,请使用以下代码:

 var query = PFQuery(className: "GameScore")
 query.getObjectInBackgroundWithId(gameScore.objectId) {
 (scoreAgain: PFObject!, error: NSError!) -> Void in
     if !error {
        NSLog("%@", scoreAgain.objectForKey("playerName") as NSString)
     } else {
        NSLog("%@", error)
    }
}

但是,当我使用官方解析代码时,我收到以下错误:

fatal error: Can't unwrap Optional.None
(lldb) 

所有这些事情几乎发生在 Xcode 的每个窗格中:

谁能告诉我哪里出了问题以及如何解决?我对 Xcode 和 Swift 比较陌生,所以我非常感谢外行术语的回答。

编辑这里是 appDelegate.swift 函数

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: NSDictionary?) -> Bool {

    // Connect to Parse using the keys provided

    Parse.setApplicationId("xxx", clientKey: "xxx")

    // Store Data to Parse

    var gameScore = PFObject(className: "GameScore")
    gameScore.setObject(1337, forKey: "score")
    gameScore.setObject("Sean Plott", forKey: "playerName")
    gameScore.saveInBackgroundWithBlock {
        (success: Bool!, error: NSError!) -> Void in
        if success {
            NSLog("Object created with id: \(gameScore.objectId)")
        } else {
            NSLog("%@", error)
        }
    }

    var query = PFQuery(className: "GameScore")
    query.getObjectInBackgroundWithId(gameScore.objectId) {
        (scoreAgain: PFObject!, error: NSError!) -> Void in
        if !error {
            NSLog("%@", scoreAgain.objectForKey("playerName") as NSString)
        } else {
            NSLog("%@", error)
        }
    }



    // Override point for customization after application launch.
    return true
}

非常感谢。

添加新代码供用户查看:

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: NSDictionary?) -> Bool {

    // Connect to Parse using the keys provided

    Parse.setApplicationId("xxxx", clientKey: "xxxx")

    // Store Data to Parse

    var gameScore = PFObject(className: "GameScore")
    gameScore.setObject(1337, forKey: "score")
    gameScore.setObject("Sean Plott", forKey: "playerName")
    gameScore.saveInBackgroundWithBlock {
        (success: Bool!, error: NSError!) -> Void in
        if (success ?? false) {
            NSLog("Object created with id: \(gameScore.objectId)")
        } else {
            NSLog("%@", error)
        }
    }

    var query = PFQuery(className: "GameScore")
    query.getObjectInBackgroundWithId(gameScore.objectId) {
        (scoreAgain: PFObject!, error: NSError!) -> Void in
        if error == nil {
            NSLog("%@", scoreAgain.objectForKey("playerName") as NSString)
        } else {
            NSLog("%@", error)
        }
    }



    // Override point for customization after application launch.
    return true
}

【问题讨论】:

  • 你的NSLog 输出是什么?您的对象是使用 ID 创建的,还是打印了错误?无论如何,这听起来可能是一个 Parse 错误。如果找不到对象,我会假设它使用提供的NSError 实例执行回调。
  • 我很惊讶这个编译。尝试将if !error 替换为if error != nil
  • 实际上,我刚刚注意到您的堆栈跟踪实际上确实调用了回调。 scoreAgain 真的有价值吗?您可以在使用前尝试将其与nil 进行比较吗?如果没有,我建议您将回调的方法签名更改为:(scoreAgain: PFObject?, error: NSError?) -> Void,以强制您的代码检查值。
  • 抱歉,请尝试将 if !error 替换为 if error == nil
  • @CraigOtis 更改了行以匹配此:(scoreAgain: PFObject?, error: NSError?) -> Void 然后我收到此错误:PFObject 没有名为“objectForKey”的数字 - 真的抱歉,我说我有点菜鸟,我不知道如何解决这个问题。 :(

标签: ios swift parse-platform


【解决方案1】:

这个 Parse 示例是在 Swift 处于 Beta 版时的 6 月编写的。 Swift 不断发展,所以他们正在做的一些事情在 Swift 中不再合法。

首先,您不能再检查可选变量error 是否为nilif !error。相反,您必须像这样显式检查nilif error == nil

其次,success 被声明为隐式展开的可选项。检查是否为trueif success 不再有效。你可以做if success == true,但如果successnil,这会崩溃。相反,您可以使用if (success ?? false)。这使用 nil 合并运算符 来安全地解开可选的 Bool(如果它有一个值),或者如果 Boolnil,它使用 false。无论哪种方式,if 只有在 Booltrue 时才会成功。

【讨论】:

  • 非常感谢您的帮助:)
  • 请注意,将Optional<T>T 进行比较,如if success == true,实际上是一种安全操作。当您在一个类型上定义 == 时,Swift 会自动连接比较案例,其中一个或另一个或两个 Ts 是 nil
  • @rikkigibson,如果success 被声明为Bool! 并且它是nil,它会在执行if success == nilfatal error: unexpectedly found nil while unwrapping an Optional value 时崩溃。我刚刚在操场上验证了这一点。如果successBool?,那么你可以if success == nil,它不会崩溃。
  • 很高兴知道。将其称为原因号 543,以不使用隐式展开的选项。
  • 是的,它们很危险。它们适用于您知道将在使用之前设置的属性(例如 iOS 如何将它们用于 IBOutlets)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-08-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多