2011-04-14 40 views
9
@interface someview:UIView{ 
    NSTimer* timer; 
} 
@end 

@implementation someview 

-(void)dealloc{ 
    NSLog(@"dealloc someview"); 
    [timer invalidate]; 
    timer = nil; 
} 
-(void)runTimer{ 
// 
} 
-(void)someMethod{ 

    timer = [NSTimer timerWithTimeInterval:2.0f target:self selector:@selector(runTimer) userInfo:nil repeats:YES]; 
} 

@end 

釋放someview不會調用dealloc並且定時器繼續運行。NSTimer禁用UIView中的dealloc

如果我註釋掉「timer = [NSTimer schedule ....」部分,dealloc將被調用。這意味着我的代碼的所有其他部分正常工作,計時器是罪魁禍首。 runTimer方法是空的,這意味着它只是計時器與我混淆。

回答

14

NSTimer保留目標。因此,在視圖解除分配之前,定時器必須失效。

+0

在上海華盈的的dealloc只叫,我把「[someview KillTimer函數]和[someview發佈],定時器得到無效,但dealloc中仍然不會被調用 – ssj 2011-04-14 22:42:35

+0

然後其他的東西仍然保留視圖 – bbum 2011-04-14 23:03:43

+0

不知道爲什麼我實施的killtimer方法沒有工作我第一次嘗試它..但它現在起作用 – ssj 2011-04-15 01:10:36

21

我認爲在UIView中使用NSTimer時最好的解決方案是覆蓋removeFromSuperview方法;

- (void)removeFromSuperview 
{ 
    [timer invalidate]; 
    timer = nil; 

    [super removeFromSuperview]; 
} 

要記住這裏的唯一的事情是,你需要確保timer不是零對象,因爲removeFromSuperview還可以獲得自動從其他的UIView的超級dealloc的方法調用。你可以包裝在一個條件來檢查。

+0

removeFromSuperview將發送釋放消息的視圖。所以我認爲我們可以在dealloc中使用它 – SNR 2012-02-10 06:49:39

+0

這對於那些使用ARC的人來說是完美的,謝謝 – BigBadOwl 2012-06-24 17:05:16

0

如上所述,定時器保留其目標。在定時器失效之前,定時器和視圖之間有一個保留週期,所以視圖不會被釋放。

當通過子類didMoveToSuperview從視圖層次結構中刪除計時器時,計時器將被視爲相關更改(例如,超級視圖更改)時被系統調用。該「removeFromSuperview」時removeFromSuperview被稱爲上的UIView

- (void)didMoveToSuperview 
{ 
    [super didMoveToSuperview]; 

    if (!self.superview) 
    { 
     [timer invalidate]; 
     timer = nil; 
    } 
} 
+0

問題不一定是由保留週期引起的,即使你對定時器有一個弱(或沒有)引用, r將被它預定的運行循環保留。 – 2015-02-12 20:19:07