var faderTimer: NSTimer?
override func viewDidLoad() {
super.viewDidLoad()
self.faderTimer = NSTimer.scheduledTimerWithTimeInterval(self.fadeTime, target: self, selector: Selector("fadeBackground"), userInfo: nil, repeats: true)
}
我需要在控制器取消之前使此计时器无效。
deinit {
//never gets called
if let timer = self.faderTimer {
self.faderTimer!.invalidate()
self.faderTimer = nil
}
}
但是,我不能把它粘在deinit()中。似乎我必须在viewWillDisappear
中使其无效。但是,我不想这样做,因为它会影响背景切换。 (从后台返回不会调用viewWillAppear,所以我必须使用通知来启动计时器,这是一个巨大的痛苦。)我宁愿在viewDidLoad上启动计时器并在deinit()上停止它。
答案 0 :(得分:6)
嗯,你不能。计时器保留您(我只是在
上停止计时器viewDidLoad
启动计时器并在deinit()
self
),并将继续这样做,直到它失效。这意味着除非您采取措施使其他地方的计时器无效,否则deinit
将永远不会被称为并且视图控制器将泄漏(它将永远不会存在,并且它将是所有内存将继续举行,以及所有财产的持有)。你必须找到另一个地方来使计时器无效;这就是它的方式。
如果您不喜欢,则不要使用NSTimer 。请改用GCD和dispatch_source_t
。这样做的好处是它基于一个块(一个闭包) - 你可以在块内部使用weak self
或unowned self
来防止自己被保留,因此你可以在{ {1}}如果你愿意的话。这正是我创建GCD-based timer class作为NSTimer的替代品的原因。
答案 1 :(得分:3)
我知道现在为时已晚,但你可以像viewWillDissappear
那样无效;
override func viewWillDisappear(animated: Bool) {
super.viewWillDisappear(animated)
if isMovingFromParentViewController() {
yourTimer.invalidate()
}
}
如果isMovingFromParentViewController
返回true,则表示用户点击后退按钮并弹出导航堆栈中的最后一个视图控制器。因此,deinit
将在真实位置被调用。