ios - 如何在进入后台后杀死 NSTimer 并在应用程序恢复事件后创建一个新计时器?

标签 ios iphone swift timer nstimer

所以我正在使用 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/

相关文章:

iphone - Objective c - UIActivityViewController 方向模式

iphone - App Store按钮

ios - 表格标题和第一个单元格之间的差距

swift - 我无法使用 Swift 添加 JSQMessagesViewController...。如何正确导入它?

ios - 向 iOS 设备发送推送通知

ios - 隐藏 AVPlayerController 全屏按钮

ios - 如何使用 Objective-C 将自定义类访问到主类中?

ios - Swift 中的不可变/可变集合

ios - 在 viewDidLoad 中调用 addSubView 时的奇怪行为

iphone - iOS获取用户信息