2015-05-04 96 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