0

我为我正在开发的应用程序创建了一个时钟,该时钟开始正常(每次计数一秒),然后每两秒冻结一次,然后每四秒,然后八秒,等等,直到它达到 20 并且应用程序崩溃,在 xcode 显示中没有错误,甚至没有Recieved Memory Warning.

我去了 Instruments,发现当使用我的时钟时,我的应用程序的内存正在以惊人的速度增加(尽管任何速度对我来说都是令人震惊的)。问题是,我无法弄清楚究竟是什么导致内存如此之高。该应用程序在 ARC 上运行,所以我知道我没有忘记发布一些东西。我唯一能想到的是,每次加载数字时,它都会存储到内存中并且永远不会释放。那是怎么回事,我不知道,如何解决它我什至没有想法。请让我知道我能做什么。这是我的代码:

-(void)updateTime {

    calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
    unsigned unitFlags = NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit | NSHourCalendarUnit | NSMinuteCalendarUnit | NSSecondCalendarUnit;
    updateTimer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(updateTime) userInfo:nil repeats:YES];

    currentTime = [NSDate date];
    dateComponents = [calendar components:unitFlags fromDate:currentTime];
    year = [dateComponents year];
    month = [dateComponents month];
    day = [dateComponents day];
    hour = [dateComponents hour];
    minute = [dateComponents minute];
    second = [dateComponents second];

    if (hour >= 12) {
        lblAMPM.text = @"PM";
    } else {
        lblAMPM.text = @"AM";
    }

    //if (isTwelveHour == YES) {
        //make a 12 hrs clock instead of 24
        if (hour >= 12) {
            hour = 12 - (24-hour);
        }
    //}

    //if midnight, show hour as 12 instead of 0
    if (hour == 0) {
        hour = 12;
    }

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

    if (minute < 10) {
        lblTime.text = [NSString stringWithFormat:@"%i:0%i:%@", hour, minute, seconds];
    } else {
        lblTime.text = [NSString stringWithFormat:@"%i:%i:%@", hour, minute, seconds];
    }

    [lblDate setText:[NSString stringWithFormat:@"%d/%d/%d", month, day, year]];

}

- (void) updateDateFirst:(int)firstComponent setSecond:(int)secondComponent{

    calendar = [NSCalendar currentCalendar];
    unsigned unitFlags = NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit | NSHourCalendarUnit | NSMinuteCalendarUnit | NSSecondCalendarUnit;
    updateTimer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(updateTime) userInfo:nil repeats:YES];

    currentTime = [NSDate date];
    dateComponents = [calendar components:unitFlags fromDate:currentTime];
    year = [dateComponents year];
    month = [dateComponents month];
    day = [dateComponents day];

    [lblDate setText:[NSString stringWithFormat:@"%d/%d/%d", firstComponent, secondComponent, year]];

}

- (void)viewDidUnload {
    lblTime = nil;
    lblAMPM = nil;
    lblDate = nil;
    [super viewDidUnload];
}

我打电话updateTimerviewDidAppear,仅供参考。

4

2 回答 2

2

NSTimer每次updateTime调用时都会创建新对象。因此,分配和运行的计时器的数量每秒增加 2 倍!

  • 一秒钟后,updateTime被调用并创建一个新的计时器。但是由于该repeats:YES选项,第一个计时器继续运行。
  • 下一秒后,两个计时器都会触发并调用updateTime。现在你有 4 个计时器。
  • 等等 ...

我不知道你updateDateFirst:的用途是什么,但它会创建另一个计时器。

所以你应该只创建一次计时器,例如在viewDidAppear. 并且不要忘记停止计时器(使用invalidate),例如在viewWillDisappear.

于 2012-08-14T06:54:17.473 回答
2

每次updateTime调用它都会创建一个新计时器,并在您调用时将其添加到当前运行循环中:

updateTimer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(updateTime) userInfo:nil repeats:YES];

运行循环保留这些计时器。因此,尽管您不断替换NSTimerivar 指向的指针,updateTimer但它们永远不会dealloc被编辑。ARC 管理每个NSTimer分配给的对象,updateTimer以便他们对它们进行匹配retain/release调用。但是,retain第一次添加时的运行循环永远不会与匹配项配对,release因为计时器正在重复并且永远不会失效。所以顺序是这样的:

  1. 你打电话- (void) updateDateFirst:(int)firstComponent setSecond:(int)secondComponent来开始事情,它会创建一个NSTimer.
  2. 此计时器在 1 秒后触发并调用updateTime,这会创建一个新计时器。原始计时器正在重复,因此它将在 1 秒内再次触发。现在你有 2 个计时器。
  3. 两个计时器大约在 1 秒后触发,调用updateTime并创建 2 个新计时器。现在你有 4 个计时器....

执行此操作的标准方法是在开始时创建 1 个重复计时器,而不是在每次调用updateTimer. 然后当你完成后,你打电话:

[updateTimer invalidate];
upateTimer = nil;

这将停止并释放计时器。

于 2012-08-14T06:55:12.363 回答