【问题标题】:Why does this clock that I created seem to never release any of it memory?为什么我创建的这个时钟似乎永远不会释放它的任何内存?
【发布时间】:2023-04-01 21:20:01
【问题描述】:

我为我正在开发的应用程序创建了一个时钟,该时钟开始正常(每次计数一秒),但随后每两秒冻结一次,然后每四秒,然后八秒,等等,直到它达到 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];
}

我在viewDidAppear 中打电话给updateTimer,仅供参考。

【问题讨论】:

    标签: objective-c memory memory-management memory-leaks


    【解决方案1】:

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

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

    运行循环保留这些计时器。因此,尽管您不断替换您的 ivar updateTimer 指向的 NSTimer,但它们永远不会被 dealloc'ed。 ARC 管理分配给updateTimer 的每个NSTimer,因此它们有匹配的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;
    

    这会停止并释放计时器。

    【讨论】:

      【解决方案2】:

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

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

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

      因此您应该只创建一次计时器,例如在viewDidAppear 中。并且不要忘记停止计时器(使用invalidate),例如在viewWillDisappear 中。

      【讨论】:

        猜你喜欢
        • 2011-05-26
        • 2018-11-08
        • 2016-01-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多