2014-11-04 2 views
1

예제 프로젝트에 문제가 있음을 발견했습니다. 레이블을 "애니메이트"한 scheduleTimer를 만든 다음 원하는 결과에 도달하면 타이머를 무효화하고 다른 하나는 "시계"로 설정합니다. 이 내가 "시계"를 시작하기 때문에 나는, 메모리는 여전히 일정한 지속 할당과 19/20 MB에 남아 힙 메모리 영구 할당 NSTimer

// 
// ViewController.m 
// 
// 
// 
// 
// 

#import "ViewController.h" 

#define ANIMATION_INTERVAL    0.07 // in secondi 
#define ANIMATION_DURATION    1 // in secondi 

@interface ViewController() 
{ 
    int contatore; 
    NSString *hour; 
    NSString *minute; 
    NSString *second; 
} 

@end 

@implementation ViewController 

- (void)viewDidLoad { 
    [super viewDidLoad]; 
    // Do any additional setup after loading the view, typically from a nib. 

    contatore = 0; 

    [self startTimeAnimation]; 


} 

- (void)didReceiveMemoryWarning { 
    [super didReceiveMemoryWarning]; 
    // Dispose of any resources that can be recreated. 
} 


-(void)startTimeAnimation 
{ 
    NSTimer * animationTimer = [NSTimer scheduledTimerWithTimeInterval:ANIMATION_INTERVAL target:self selector:@selector(timeout:) userInfo:nil repeats:YES]; 
} 

-(void)timeout: (NSTimer *)timer 
{ 
    // Simulate of the Timer Duration with a counter 
    if (contatore < ceilf(ANIMATION_DURATION/ANIMATION_INTERVAL)) 
    { 
     // Proceed with animation 
     contatore++; 

     int tempHour = arc4random_uniform(24); 
     int tempMinute = arc4random_uniform(60); 
     int tempSecond = arc4random_uniform(60); 

     if (tempHour < 10) 
     { 
      hour = [NSString stringWithFormat:@"0%d", tempHour]; 
     } 
     else 
     { 
      hour = [NSString stringWithFormat:@"%d", tempHour]; 
     } 

     if (tempMinute < 10) 
     { 
      minute = [NSString stringWithFormat:@"0%d", tempMinute]; 
     } 
     else 
     { 
      minute = [NSString stringWithFormat:@"%d", tempMinute]; 
     } 

     if (tempSecond < 10) 
     { 
      second = [NSString stringWithFormat:@"0%d", tempSecond]; 
     } 
     else 
     { 
      second = [NSString stringWithFormat:@"%d", tempSecond]; 
     } 

     _orarioLbl.text = [NSString stringWithFormat:@"%@:%@:%@", hour, minute, second]; 
    } 
    else 
    { 
     // Stops animation 
     [timer invalidate]; 
     [timer release]; 
     contatore = 0; 



     [self setActualTime]; 


     // Starts clock 
     NSTimer *clockTimer = [NSTimer timerWithTimeInterval:.5f target:self selector:@selector(updateClock) userInfo:nil repeats:YES]; 
     [[NSRunLoop mainRunLoop] addTimer:clockTimer forMode:NSRunLoopCommonModes]; 
    } 
} 

-(void)updateClock 
{ 
    [self setActualTime]; 
} 


-(void)setActualTime 
{ 
    NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init]; 

    [dateFormatter setDateFormat:@"HH"]; 
    hour = [dateFormatter stringFromDate:[NSDate date]]; 

    [dateFormatter setDateFormat:@"mm"]; 
    minute = [dateFormatter stringFromDate:[NSDate date]]; 

    [dateFormatter setDateFormat:@"ss"]; 
    second = [dateFormatter stringFromDate:[NSDate date]]; 

    _orarioLbl.text = [NSString stringWithFormat:@"%@:%@:%@", hour, minute, second]; 
    [dateFormatter release]; 
} 

@end 

를 사용하는 코드입니다. 타이머가 분 값을 업데이트하면 gif에서 볼 수 있듯이 지속적 할당이 증가합니다! 그게 어떻게 가능해? 그러나, 또한 19MB의 메모리는 단순한 시계에 비해 너무 많습니다. 그렇지 않습니까? Instruments의 프로파일 링 인 새로운 할당은 모두 CoreGraphics에 관한 것입니다!

animated gif Instruments

편집 내가 다른 기기에서 테스트 및 영구 할당은 감소했다. 나는 이유를 모른다. 그러나 나는이 방법으로 해결했다. 감사합니다.

답변

2

NSTimer은 보유 기간을 유지할 수 있습니다. self에 약한 참조를 잡고 목표로한다는 설정 : NSDateFormatter의 작성 비싸다으로

__weak typeof(self) weakSelf = self; 
NSTimer * animationTimer = [NSTimer scheduledTimerWithTimeInterval:ANIMATION_INTERVAL target:weakSelf selector:@selector(timeout:) userInfo:nil repeats:YES]; 

__weak typeof(self) weakSelf = self; 
NSTimer *clockTimer = [NSTimer timerWithTimeInterval:.5f target:weakSelf selector:@selector(updateClock) userInfo:nil repeats:YES]; 

나는 또한 당신의 dateFormatter에 대한 속성을 만들 권고 할 수있다. 그리고 왜 당신은 dateFormatter를 공개하고 있습니까? ARC를 사용하지 않습니까?

+0

아니요,이 샘플을 아직 ARC에서 변환하지 않은 가장 큰 프로젝트에 구현해야했기 때문에 ARC를 사용하지 않았습니다. 편집 : 이러한 변경 사항을 적용하면 메모리 할당이 점차 커집니다. 50/60 할당에서 1600으로갑니다! –