所以我正在使用 Swift 构建一个简单的 iOS 应用程序。我需要在应用程序进入后台后终止我的 NSTimer
,并在应用程序再次激活后创建一个新的。
最初我的解决方案是在主 Controller 文件的 ViewDidLoad()
中创建一个 NSTimer
类的计时器。这会导致我的应用出现错误。
我想我需要通过在 AppDelegate.swift 中使用 applicationDidEnterBackground()
来终止计时器。但是我不确定该怎么做。我应该在 AppDelegate.swift 还是在主 Controller 中创建计时器类?我不知道 Swift 文件如何共享类。
我在网上搜索了解决方案,但是那些帖子都太旧了,解决方案是用 Objective-C 编写的。
我绝对是个初学者。所以我希望有人能用 Swift 解释一下。
这是我的主 Controller TodoTableViewController.swift 中的代码:
import UIKit
import CoreData
class TodoTableViewController: UITableViewController, NSFetchedResultsControllerDelegate {....
...
...
override func viewDidLoad() {
super.viewDidLoad()
var fetchRequest = NSFetchRequest(entityName: "Todo")
let sortDescriptor = NSSortDescriptor(key: "dayleft", ascending: true)
fetchRequest.sortDescriptors = [sortDescriptor]
if let managedObjectContext = (UIApplication.sharedApplication().delegate as AppDelegate).managedObjectContext {
fetchResultController = NSFetchedResultsController(fetchRequest:fetchRequest, managedObjectContext: managedObjectContext, sectionNameKeyPath: nil, cacheName: nil)
fetchResultController.delegate = self
var e: NSError?
var result = fetchResultController.performFetch(&e)
todos = fetchResultController.fetchedObjects as [Todo]
if result != true {
println(e?.localizedDescription)
} }
var timer = NSTimer.scheduledTimerWithTimeInterval(10, target: self, selector:"update", userInfo:nil, repeats: true)
}
...
}
如果我要使 AppDelegate.swift 中的计时器无效,我该如何将计时器引用到我在 TodoTableViewController.swift 中创建的计时器?或者我应该将所有与计时器相关的代码放在 AppDelegate.swift 中?
更新
我尝试过使用 NSNotificationCenter,这是我的代码。
import UIKit
import CoreData
class TodoTableViewController: UITableViewController, NSFetchedResultsControllerDelegate {
...
var timer = NSTimer.scheduledTimerWithTimeInterval(10, target: self, selector:"viewDidLoad", userInfo:nil, repeats: true)
func update(){
.....
}
override func viewDidLoad() {
super.viewDidLoad()
...
let notificationCenter = NSNotificationCenter.defaultCenter()
notificationCenter.addObserver(self, selector: "didEnterBackground", name: "UIApplicationDidEnterBackgroundNotification", object: UIApplication.sharedApplication())
notificationCenter.addObserver(self, selector: "didBecomeActive", name: "UIApplicationWillEnterForegroundNotification", object: UIApplication.sharedApplication())
}
func didEnterBackground() {
timer.invalidate()
}
func didBecomeActive() {
var timer = NSTimer.scheduledTimerWithTimeInterval(10, target: self, selector:"update", userInfo:nil, repeats: true)
}
...
}
由于定时器是在didBecomeActive()
中声明的,在didEnterBackground()
中出现错误:does not have a member named "timer"。如果我在 didBecomeActive()
之外声明 timer
就像我上面发布的代码一样,就会出现“调用中的额外参数‘selector’”的错误。我已经将函数 update()
解析为选择器。我不知道这个错误是从哪里来的。
最佳答案
更新了您的代码并添加了一些评论:
class TodoTableViewController: UITableViewController, NSFetchedResultsControllerDelegate
//better to instantiate timer inside viewDidLoad
var timer: NSTimer!
func update(){ }
override func viewDidLoad() {
super.viewDidLoad()
startTimer()
let notificationCenter = NSNotificationCenter.defaultCenter()
//UIApplicationDidEnterBackgroundNotification & UIApplicationWillEnterForegroundNotification shouldn't be quoted
notificationCenter.addObserver(self, selector: "didEnterBackground", name: UIApplicationDidEnterBackgroundNotification, object: nil)
notificationCenter.addObserver(self, selector: "didBecomeActive", name: UIApplicationWillEnterForegroundNotification, object: nil)
}
func didEnterBackground() {
self.timer.invalidate()
}
func didBecomeActive() {
startTimer()
}
func startTimer() {
self.timer = NSTimer.scheduledTimerWithTimeInterval(10, target: self, selector:"update", userInfo:nil, repeats: true)
}
}
另请注意,NSTimer
强烈保持它的 target
。因此,当关闭 viewcontroller - 计时器应该明确无效。否则会发生内存泄漏,TodoTableViewController
将永远不会被销毁。
关于ios - 如何在进入后台后杀死 NSTimer 并在应用程序恢复事件后创建一个新计时器?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27455122/