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!)")
}
}
}
}
我的代码有一个奇怪的错误,我很难解决。
我已经使用 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!)")
}
}
}
}