Swift - 应用程序在设置 UserDefaults 后崩溃
Swift - app crashes after setting UserDefaults
我正在尝试在我的应用程序中实现 "always logged in" 功能。问题是,如果我重新启动我的应用程序,它就会崩溃。这就是我所做的:
设置用户默认值:
@objc func loginButtonTapped(_ sender: Any) {
let email = self.emailTextField.text!.trimmingCharacters(in: .whitespacesAndNewlines)
let password = self.passwordTextField.text!.trimmingCharacters(in: .whitespacesAndNewlines)
// start button animation
loginButton.startAnimation()
let qualityOfServiceClass = DispatchQoS.QoSClass.background
let backgorundQueue = DispatchQueue.global(qos: qualityOfServiceClass)
backgorundQueue.async {
// check if account details correct
Auth.auth().signIn(withEmail: email, password: password) { (result, error) in
if error != nil {
DispatchQueue.main.async {
// error -> stop animation
self.loginButton.stopAnimation(animationStyle: .shake, revertAfterDelay: 0) {
self.errorLabel.text = error!.localizedDescription
self.errorLabel.alpha = 1
}
}
}else {
// correct acount details -> login
DispatchQueue.main.async {
UserDefaults.standard.set(true, forKey: "isLoggedIn")
UserDefaults.standard.synchronize()
// transition to home ViewController
self.transitionToHome()
}
}
}
}
}
正在检查用户默认值:
class MainNavigationControllerViewController: UINavigationController {
override func viewDidLoad() {
super.viewDidLoad()
if isLoggedIn() {
let homeController = MainViewController()
viewControllers = [homeController]
}
}
fileprivate func isLoggedIn() -> Bool {
return UserDefaults.standard.bool(forKey: "isLoggedIn")
}
}
用户通过Firebase登录,所有数据都存储在Cloud Firestore中。
错误
cell.customWishlistTapCallback = {
let heroID = "wishlistImageIDX\(indexPath)"
cell.theView.heroID = heroID
let addButtonHeroID = "addWishButtonID"
self.addButton.heroID = addButtonHeroID
// track selected index
self.currentWishListIDX = indexPath.item
let vc = self.storyboard?.instantiateViewController(withIdentifier: "WishlistVC") as? WishlistViewController
vc?.wishList = self.dataSourceArray[self.currentWishListIDX]
// pass drop down options
vc?.theDropDownOptions = self.dropDownButton.dropView.dropDownOptions
vc?.theDropDownImageOptions = self.dropDownButton.dropView.dropDownListImages
// pass current wishlist index
vc?.currentWishListIDX = self.currentWishListIDX
// pass the data array
vc?.dataSourceArray = self.dataSourceArray
// set Hero ID for transition
vc?.wishlistImage.heroID = heroID
vc?.addWishButton.heroID = addButtonHeroID
// allow MainVC to recieve updated datasource array
vc?.dismissWishDelegate = self
vc?.theTableView.tableView.reloadData()
self.present(vc!, animated: true, completion: nil)
}
Thread 1: EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0)
行:
let vc = self.storyboard?.instantiateViewController(withIdentifier: "WishlistVC") as! WishlistViewController
我想这并不像我想象的那么容易。有谁知道应用程序崩溃的原因以及我如何解决这个问题? :)
您正在使用简单的初始化程序 (MainViewController()
) 创建 MainViewController
实例,而不是从故事板实例化它。因此,任何 @IBOutlet
属性都将是 nil
,因为它是分配这些对象实例并将它们分配给属性的故事板进程。
您需要向主视图控制器场景添加一个标识符(如果它还没有)并使用它来实例化视图控制器实例。例如。假设场景标识符是 "MainScene" 你会得到类似的东西:
override func viewDidLoad() {
super.viewDidLoad()
if isLoggedIn() {
let homeController = UIStoryboard(name: "Main", bundle: nil).instantiateViewControllerWithIdentifier("MainScene")
viewControllers = [homeController]
}
}
您更新后的问题中的崩溃表明标识符为 WishlistVC
的场景没有将其 class 设置为 WishlistViewController
或者未找到,因此强制沮丧崩溃。
我正在尝试在我的应用程序中实现 "always logged in" 功能。问题是,如果我重新启动我的应用程序,它就会崩溃。这就是我所做的:
设置用户默认值:
@objc func loginButtonTapped(_ sender: Any) {
let email = self.emailTextField.text!.trimmingCharacters(in: .whitespacesAndNewlines)
let password = self.passwordTextField.text!.trimmingCharacters(in: .whitespacesAndNewlines)
// start button animation
loginButton.startAnimation()
let qualityOfServiceClass = DispatchQoS.QoSClass.background
let backgorundQueue = DispatchQueue.global(qos: qualityOfServiceClass)
backgorundQueue.async {
// check if account details correct
Auth.auth().signIn(withEmail: email, password: password) { (result, error) in
if error != nil {
DispatchQueue.main.async {
// error -> stop animation
self.loginButton.stopAnimation(animationStyle: .shake, revertAfterDelay: 0) {
self.errorLabel.text = error!.localizedDescription
self.errorLabel.alpha = 1
}
}
}else {
// correct acount details -> login
DispatchQueue.main.async {
UserDefaults.standard.set(true, forKey: "isLoggedIn")
UserDefaults.standard.synchronize()
// transition to home ViewController
self.transitionToHome()
}
}
}
}
}
正在检查用户默认值:
class MainNavigationControllerViewController: UINavigationController {
override func viewDidLoad() {
super.viewDidLoad()
if isLoggedIn() {
let homeController = MainViewController()
viewControllers = [homeController]
}
}
fileprivate func isLoggedIn() -> Bool {
return UserDefaults.standard.bool(forKey: "isLoggedIn")
}
}
用户通过Firebase登录,所有数据都存储在Cloud Firestore中。
错误
cell.customWishlistTapCallback = {
let heroID = "wishlistImageIDX\(indexPath)"
cell.theView.heroID = heroID
let addButtonHeroID = "addWishButtonID"
self.addButton.heroID = addButtonHeroID
// track selected index
self.currentWishListIDX = indexPath.item
let vc = self.storyboard?.instantiateViewController(withIdentifier: "WishlistVC") as? WishlistViewController
vc?.wishList = self.dataSourceArray[self.currentWishListIDX]
// pass drop down options
vc?.theDropDownOptions = self.dropDownButton.dropView.dropDownOptions
vc?.theDropDownImageOptions = self.dropDownButton.dropView.dropDownListImages
// pass current wishlist index
vc?.currentWishListIDX = self.currentWishListIDX
// pass the data array
vc?.dataSourceArray = self.dataSourceArray
// set Hero ID for transition
vc?.wishlistImage.heroID = heroID
vc?.addWishButton.heroID = addButtonHeroID
// allow MainVC to recieve updated datasource array
vc?.dismissWishDelegate = self
vc?.theTableView.tableView.reloadData()
self.present(vc!, animated: true, completion: nil)
}
Thread 1: EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0)
行:
let vc = self.storyboard?.instantiateViewController(withIdentifier: "WishlistVC") as! WishlistViewController
我想这并不像我想象的那么容易。有谁知道应用程序崩溃的原因以及我如何解决这个问题? :)
您正在使用简单的初始化程序 (MainViewController()
) 创建 MainViewController
实例,而不是从故事板实例化它。因此,任何 @IBOutlet
属性都将是 nil
,因为它是分配这些对象实例并将它们分配给属性的故事板进程。
您需要向主视图控制器场景添加一个标识符(如果它还没有)并使用它来实例化视图控制器实例。例如。假设场景标识符是 "MainScene" 你会得到类似的东西:
override func viewDidLoad() {
super.viewDidLoad()
if isLoggedIn() {
let homeController = UIStoryboard(name: "Main", bundle: nil).instantiateViewControllerWithIdentifier("MainScene")
viewControllers = [homeController]
}
}
您更新后的问题中的崩溃表明标识符为 WishlistVC
的场景没有将其 class 设置为 WishlistViewController
或者未找到,因此强制沮丧崩溃。