swift 在应用程序恢复时解析注销后应用程序崩溃

swift parse app crashes after logout when app resumes

我的代码有一个奇怪的错误,我很难解决。

我已经使用 swift 构建了一个应用程序并进行了解析。您登录后,将被带到 table 视图的主页。现在,如果您已登录,离开并返回应用程序,一切都很好。

但是,当我注销时,用户会返回到登录屏幕。现在,如果用户离开该应用程序,但又回来了,该应用程序会崩溃,并在展开可选值时给我错误 unexpectedly found nil 。

对我来说,可能发生的事情毫无意义。当应用程序从头开始重新启动时,用户设置为 nil,然后用户登录,一切都很酷。当您注销时,用户将被设置回 nil 并转到登录屏幕。如果你恢复应用程序,崩溃。

这是我注销用户的方式的问题吗?

相关代码贴在下面..

登录页面:

@IBAction func loginButton(sender: AnyObject) {
    //checks if there is a matching username with a matching password. if so, lets the user log in.



    PFUser.logInWithUsernameInBackground(username.text, password: userPassword.text) {
        (user: PFUser?, error: NSError?) -> Void in
        if user != nil {
            // Do stuff after successful login.
            //go to main table view
            //get current user
            //display current users locations
            println("login success")


            //shows home screen after successful login.
            self.performSegueWithIdentifier("showHomeFromLogin", sender: self)
        } else {
            // The login failed. Check error to see why.
            //display error?
            self.displayAlert("Login Failed", alertMessage: "Double check to make sure the username and password are correct.")
            println("login failed")
        }
    }

}


var activeField: UITextField?





override func viewDidLoad() {
    super.viewDidLoad()


    username.delegate = self
    userPassword.delegate = self

    registerForKeyboardNotifications()




    // Do any additional setup after loading the view.
    //setup so when we tap outside the edit, we close keyboard.
    var tap: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: "DismissKeyboard")
    view.addGestureRecognizer(tap)
}


override func viewDidAppear(animated: Bool) {
    if PFUser.currentUser() != nil {
        self.performSegueWithIdentifier("showHomeFromLogin", sender: self)
    }

}

在用户登出的主页上:

@IBAction func logoutButton(sender: AnyObject) {

    PFUser.logOut()
    var currentUser = PFUser.currentUser() // this will now be nil
    self.performSegueWithIdentifier("logoutSegue", sender: self)
}

override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.

    NSNotificationCenter.defaultCenter().addObserver(self, selector: "launchSync", name: UIApplicationDidBecomeActiveNotification, object: nil)

    //setting table view datasource and delegate.
    self.tableView.dataSource = self
    self.tableView.delegate = self



    var currentUser = PFUser.currentUser()
    println(currentUser)

}

在这里休息我觉得就行query.whereKey("User", equalTo:PFUser.currentUser()!):

func launchSync() {
    var query = PFQuery(className:"ParseLighthouse")
    query.whereKey("User", equalTo:PFUser.currentUser()!)
    query.findObjectsInBackgroundWithBlock {
        (objects: [AnyObject]?, error: NSError?) -> Void in

        if error == nil {
            // The find succeeded.
            println("Successfully retrieved \(objects!.count) lighthouses.")
            // Do something with the found objects
            if let light = objects as? [PFObject] {
                for object in light {
                    println(object.objectId)
                }
            }
            println(objects?.count)
            self.syncToLighthouse(objects!)
        } else {
            // Log details of the failure
            println("Error: \(error!) \(error!.userInfo!)")
        }
    }
}

这个launchsync函数是在我的主屏幕上的view did appear方法中调用的。是否有可能在执行注销 segue 时,主视图控制器仍然 运行 在后台,所以当我恢复时,该代码现在无法找到用户,因为它已设置回 nil?

如果条件值有可能为零,那么您需要在使用前检查条件。当当前没有登录用户时,PFUser.currentUser() 将 return 为零。当您使用 ! 强制解包此值时,您会得到一个异常。

您可以更改代码以有条件地展开值 -

func launchSync() {
    if let currentUser=PFUser.currentUser() {
        var query = PFQuery(className:"ParseLighthouse")
        query.whereKey("User", equalTo:currentUser)
        query.findObjectsInBackgroundWithBlock {
            (objects: [AnyObject]?, error: NSError?) -> Void in

            if error == nil {
                // The find succeeded.
                println("Successfully retrieved \(objects!.count) lighthouses.")
                // Do something with the found objects
                if let light = objects as? [PFObject] {
                    for object in light {
                        println(object.objectId)
                    }
                }
                println(objects?.count)
                self.syncToLighthouse(objects!)
            } else {
                // Log details of the failure
                println("Error: \(error!) \(error!.userInfo!)")
            }
        }
    } 
}

在下一行

NSNotificationCenter.defaultCenter().addObserver(self, selector: "launchSync", name: UIApplicationDidBecomeActiveNotification, object: nil)

你说只要应用程序激活就调用 launchSync 函数。

正如 Paulw11 所提到的,在该函数中,您在 PFUser.currentUser() 上强制解包(使用!),当用户注销时,这将 return 为零。

您可以通过确保当前用户不是 nil 来解决此问题

func launchSync() {
    if (PFUser.currentUser() != nil) {
        var query = PFQuery(className:"ParseLighthouse")
        query.whereKey("User", equalTo:PFUser.currentUser()!)
        query.findObjectsInBackgroundWithBlock {
            (objects: [AnyObject]?, error: NSError?) -> Void in

            if error == nil {
                // The find succeeded.
                println("Successfully retrieved \(objects!.count) lighthouses.")
                // Do something with the found objects
                if let light = objects as? [PFObject] {
                    for object in light {
                        println(object.objectId)
                    }
                }
                println(objects?.count)
                self.syncToLighthouse(objects!)
            } else {
                // Log details of the failure
                println("Error: \(error!) \(error!.userInfo!)")
            }
        }
    }
}