【问题标题】:Property linked to users defaults causing app to crash链接到用户默认值的属性导致应用程序崩溃
【发布时间】:2016-12-06 18:01:03
【问题描述】:

我的初始视图控制器中的属性是在调用 AppDelegate 函数 didFinishLaunchingWithOptions 之前还是之后设置的?

这是 AppDelegate 中的代码。当我的应用第一次启动时,如果“CurrentDateBool”的用户默认值尚未设置,它会设置为 true。

  func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {

    if UserDefaults.standard.value(forKey: "currentDateBool") == nil {
      UserDefaults.standard.setValue(true, forKey: "currentDateBool")
    }
    return true
}

这是我的初始视图控制器。这会使我的应用程序在 currentDateBool 属性上崩溃,因为它是 nil。但是,它不应为 nil,因为它在 AppDelegate 中将其设置为 true。我认为 AppDelegate 在初始视图控制器之前设置。有人可以澄清设置属性的顺序吗?

class TimestampTableViewController: UITableViewController {

  var currentDateBool = UserDefaults.standard.value(forKey: "currentDateBool") as! Bool

  override func viewDidLoad() {
    super.viewDidLoad()  
  }
 ...
}

如果我在 viewDidLoad 中将 currentDateBool 属性设置为用户默认值,我可以让它工作。

class TimestampTableViewController: UITableViewController {

  var currentDateBool = true

  override func viewDidLoad() {
    super.viewDidLoad()  
    currentDateBool = UserDefaults.standard.value(forKey: "currentDateBool") as! Bool
  }
 ...
}

【问题讨论】:

  • "如果我在 viewDidLoad 中将 currentDateBool 属性设置为用户默认值,我可以让它工作。"那就这样做吧!
  • @matt 我做到了!哈哈。我只是想了解为什么当我不这样做时它会崩溃。我认为 AppDelegate 在我的属性设置之前被调用,所以我不明白它为什么会崩溃。
  • TimestampTableViewController 是你的根视图控制器吗?您使用的是主情节提要吗?
  • @matt 是的,这是我的根视图控制器,我正在使用主故事板

标签: ios swift


【解决方案1】:

如果我将currentDateBool 属性设置为viewDidLoad 中的用户默认值,我可以让它工作

确实如此。这正是你应该做的。

您正在使用主情节提要。这意味着您的初始界面是从情节提要加载的,didFinishLaunchingWithOptions 中的代码运行之前。因此,虽然 TimestampTableViewController 还没有 view,但它确实 exist — 这意味着它已经被实例化,因此它的属性已经被赋予了它们的初始值。

要知道这是真的,只需制作一个基本的 vanilla 项目,如下所示:

// in the app delegate

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
    print("one")
    return true
}

// in the main view controller

class ViewController: UIViewController {
    let what : Void = {print("two")}()
}

您将在控制台中看到two,然后是one

但是如果你将what 移动到viewDidLoad,你会看到one,然后是two。这是因为在这种情况下,视图控制器的 view 直到 应用程序委托中的代码运行后才会加载。

【讨论】:

  • 谢谢,有道理!
猜你喜欢
  • 2019-03-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-10-21
  • 2016-06-04
  • 2011-08-24
  • 2014-05-03
  • 1970-01-01
相关资源
最近更新 更多