持久分配堆内存NSTimer

时间:2014-11-04 10:59:56

标签: ios objective-c memory-management nstimer nsrunloop

我发现我的示例项目存在问题。我只是简单地创建了一个#14; animate"一个标签,然后,当我达到我想要的结果时,我使计时器无效,我又设置了另一个,这次是#34;时钟"。 这是我使用的代码

//
//  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

由于我启动了#34;时钟&#34;,内存仍然保持在19/20 MB并且持续持续分配。当计时器更新分钟值时,持久分配会增加,如您在gif中看到的那样!这怎么可能?然而,对于一个简单的时钟来说,19MB的内存也是太多了,不是吗? 对仪器进行概要分析,新的分配都是关于CoreGraphics的!

animated gif Instruments

编辑我在另一台设备上测试了它,持续分配减少了。我不知道为什么,但我这样解决了。感谢

1 个答案:

答案 0 :(得分:2)

NSTimer保留其目标,这可能会导致保留周期。获取self的弱引用并将其设置为目标:

__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创建一个属性,因为NSDateFormatter的创建成本很高。你为什么要发布dateFormatter?你没有使用ARC吗?