我的应用程序需要执行一些清理任务 - 在启动时,在显示初始视图控制器之前,删除本地存储的旧数据。
这是因为初始视图控制器在初始化时加载现有数据,并将其显示在表视图中。
我设置了几个断点,发现初始视图控制器的初始值设定项(init?(coder aDecoder: NSCoder)
)在 application(_:didFinishLaunchingWithOptions)
之前运行 - 甚至在{{1}之前,确切地说。
我可以将清理代码放在视图控制器的初始化程序的最顶层,但我希望将清理逻辑与任何特定屏幕分离。 该视图控制器最终可能不会成为初始视图控制器。
覆盖app delegate的application(_:**will**FinishLaunchingWithOptions)
方法并将我的清理代码放在那里 完成工作,但是......
是不是有更好/更优雅的方式?
注:作为参考,相关方法的执行顺序为 如下:
- AppDelegate.init()
- ViewController.init()
- AppDelegate.application(_:willFinishLaunchingWithOptions:)
- AppDelegate.application(_中:didFinishLaunchingWithOptions:)
- ViewController.viewDidLoad()
醇>
清理任务不冗长,不需要异步运行:相反,我更喜欢我的初始视图控制器甚至不实例化直到它完成(我 am 意识到如果需要很长时间才能启动,系统会终止我的应用程序。但是,它只是删除了一些本地文件,没什么大不了的。)。
我问这个问题主要是因为,在故事板出现之前,应用启动代码看起来像这样:
init()
...但现在,因为主要故事板加载发生在幕后,视图控制器在任何app委托方法运行之前初始化。
我不正在寻找需要向我的初始视图控制器添加自定义代码的解决方案。
答案 0 :(得分:4)
我不确定是否有更优雅的方式,但肯定还有其他一些方法......
如果我的初步观点,我更喜欢 控制器甚至不会被实例化直到它完成
这不是问题。您所要做的就是从UIMainStoryboardFile
中删除NSMainNibFile
或Info.plist
密钥,该密钥告诉UIApplicationMain
应该加载哪个UI。随后你运行你的"清理逻辑"在AppDelegate
中,一旦完成,您就会自己启动UI,如示例中所示。
替代解决方案是创建UIApplicationMain
的子类,并在加载UI之前在那里运行清理。
请参阅下面的应用生命周期:
答案 1 :(得分:0)
您可以在初始ViewController上添加UIImageView,它将包含应用的启动图像。
在viewDidLoad()中...使imageview.hidden属性为False ...清理操作和清理任务完成后,使imageview.hidden属性为TRUE。
由此用户将不知道您正在做什么工作,并且这种方法在许多公认的应用程序中使用。
答案 2 :(得分:0)
我遇到了非常相似的情况
我需要运行代码的地方,只有在 didFinishLaunchingNotification 之后才准备好
我想出了这个模式,它也适用于状态恢复
var finishInitToken: Any?
required init?(coder: NSCoder) {
super.init(coder: coder)
finishInitToken = NotificationCenter.default.addObserver(forName: UIApplication.didFinishLaunchingNotification, object: nil, queue: .main) { [weak self] (_) in
self?.finishInitToken = nil
self?.finishInit()
}
}
func finishInit() {
...
}
override func decodeRestorableState(with coder: NSCoder) {
// This is very important, so the finishInit() that is intended for "clean start"
// is not called
if let t = finishInitToken {
NotificationCenter.default.removeObserver(t)
}
finishInitToken = nil
}
你也可以为 willFinishLaunchingWithOptions 做一个通知