2011-04-14 2 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 

일부보기를 해제해도 dealloc은 호출되지 않고 타이머는 계속 실행됩니다.NSTimer는 UIView에서 dealloc을 비활성화합니다.

"timer = [NSTimer schedule ...."부분을 주석 처리하면 dealloc가 호출됩니다. 즉, 내 코드의 다른 모든 부분이 올바르게 작동하고 타이머가 범인이라는 의미입니다. runTimer 메서드는 비어 있습니다. 즉, 저와 함께 장난하는 타이머입니다.

답변

14

NSTimer는 표적을 보유합니다. 따라서보기가 dealloc되기 전에 타이머를 무효화해야합니다.

+0

에서 호출 한 경우에만 호출되는 'removeFromSuperview'는 내가 "[someview의 killtimer] 및 [someview 자료는, 타이머가 무효화있어하지만 할당 해제는 여전히 불리는되지 않습니다 넣어 – ssj

+0

다음 다른 뭔가가보기를 유지하고 있습니다. – bbum

+0

내가 구현 한 killtimer 메서드가 처음 시도했을 때 작동하지 않는 이유를 모르겠지만 지금 작동합니다. – ssj

21

UIView 내부에서 NSTimer를 사용할 때 가장 좋은 해결책은 removeFromSuperview 메서드를 재정의하는 것이라고 생각합니다.

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

    [super removeFromSuperview]; 
} 

여기서 명심해야 할 유일한 것은 당신이 removeFromSuperview이 자동으로 다른 UIView의의 슈퍼 할당 해제의 방법에서 전화를받을 수 있기 때문에 그 타이머가 전무 대상이 아닌 확인해야한다는 것입니다. 확인하려면 조건부로 감쌀 수 있습니다.

+0

removeFromSuperview가보기에 릴리스 메시지를 보냅니다. – SNR

+0

이것은 ARC 덕분에 적합합니다 – BigBadOwl

0

위에서 언급했듯이 타이머는 목표를 유지합니다. 타이머가 무효화 될 때까지 타이머와 뷰 사이에 유지주기가 있으므로보기가 할당 취소되지 않습니다.

didMoveToSuperview의 서브 클래 싱을 통해 뷰 계층 구조에서 타이머를 제거하면 뷰 관련 변경 사항 (예 : 수퍼 뷰 변경 사항)이있을 때 시스템에서이를 호출합니다. removeFromSuperview은 슈퍼 뷰의 할당 해제에 UIView의

- (void)didMoveToSuperview 
{ 
    [super didMoveToSuperview]; 

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

문제는 유지 사이클에 의해 반드시 야기되는 것은 아니며, 타이머에 대한 참조가 약하거나 (또는 ​​없음) r은 예정된 실행 루프에 의해 유지됩니다. –

관련 문제