2015-05-04 94 views
-2
var faderTimer: NSTimer? 
override func viewDidLoad() { 
    super.viewDidLoad() 

    self.faderTimer = NSTimer.scheduledTimerWithTimeInterval(self.fadeTime, target: self, selector: Selector("fadeBackground"), userInfo: nil, repeats: true) 
} 

我需要在控制器定义之前使这个定时器无效。如何在viewWillDisappear中不执行NSTimer而使其失效/取消?

deinit { 
    //never gets called 
    if let timer = self.faderTimer { 
     self.faderTimer!.invalidate() 
     self.faderTimer = nil 
    } 
} 

但是,我不能将它粘在deinit()中。看起来我必须在viewWillDisappear内使它无效。但是,我不想这样做,因为它会扰乱背景切换。 (从后台返回不会调用viewWillAppear,所以我必须使用通知来启动计时器,这是一个巨大的痛苦。)我宁愿在viewDidLoad上启动计时器,并在deinit()上停止它。

+0

对不起,你能澄清一下'viewWillDisappear'中的错误吗?这不仅仅是因为用户背景的应用程序,所以有什么问题? – matt

回答

6

我宁愿刚刚启动定时器上viewDidLoad并停止它deinit()

好了,你不能。定时器正在保留你(self),并将继续这样做直至失效。这意味着,除非您采取措施使其他地方的计时器无效,否则deinit将永远不会被称为,并且视图控制器将泄漏(它永远不会存在,并且它将保存的所有内存及其所有属性的内存,将继续举行)。您必须找到另一个地方来使计时器失效;就是那样子。

如果您不喜欢那样,那么请不要使用NSTimer。改为使用GCD和dispatch_source_t。这具有以块为基础的优点 - 您可以在块内部使用weak selfunowned self以防止自己被保留,因此如果您愿意,可以使定时器在deinit内无效。这就是为什么我创建了一个GCD-based timer class,作为NSTimer的替代品。

+0

什么是最好的地方做viewWillDisappear?问题是,当我在那里做的时候,它不会在背景入口处调用。因此我需要实施通知中心,使代码复杂化。 – Jess

+0

'viewWillDisappear'是一个很好的去处。当这个视图控制器的视图即将被从界面中取出时,保证被调用,这正是你想知道的。 – matt

+0

“问题是,当我在那里做它,它不会被称为背景入口​​”那么,什么?你没有解释那是什么问题。你进入后台,计时器停止。你回来了,定时器再次运行。这不是问题。问题是什么时候你的视图控制器的存在时间 - 它不能,因为定时器仍在运行,仍然保留它。你必须为此做点什么。这就是NSTimer内存管理的本质。 – matt

2

我知道这太晚了,但你可以像viewWillDissappear那样对其进行评估;

override func viewWillDisappear(animated: Bool) { 

    super.viewWillDisappear(animated) 

    if isMovingFromParentViewController() { 
     yourTimer.invalidate() 
    } 
} 

如果isMovingFromParentViewController返回true,则意味着用户点击后退按钮和弹出到最后视图控制器在导航堆栈。所以,deinit将被称为真正的地方。

+1

非常感谢! isMovingFromParentViewController正是我所需要的:) – Lilo