【问题标题】:iPhone SDK: Does 3.0 clear the cache of a imageNamed? Because 2.2.1 doesn't!iPhone SDK:3.0 会清除 imageNamed 的缓存吗?因为 2.2.1 没有!
【发布时间】:2009-06-20 19:39:45
【问题描述】:

我正在为 iPhone 创建一个应用程序,其中包含多个按钮,它们都为同一个 UIImageView 设置动画。它在模拟器中运行良好(就像几乎所有应用程序一样),但在设备上它可以很好地播放动画,但重复按下按钮应用程序退出。到目前为止,我已经实现了 2 个按钮。这是按下它们时会发生的情况。 好的,当我的应用程序启动时,我有 44 MB 的可用内存,然后当我按下启动动画的 2 个按钮中的第一个时,可用内存下降到 31 并上升到 32,然后当我按下第二个按钮时,可用内存下降到 9,然后爬升到 24,然后奇怪地缓慢下降到 10。如果然后按下第一个按钮,则可用内存将攀升至 14MB 并且在重复按下这些按钮的情况下,应用程序内存将下降至 4 到 3 MB 并退出。在仪器中没有泄漏。这是我的代码,以防任何人都可以发现我的内存问题潜伏在哪里。 (顺便说一句,我仍在 2.2.1 上开发,因为如果我升级到 3.0,我将无法在设备上测试我的应用程序,因为我还没有注册苹果开发者计划,我按照在线教程获得应用到仅适用于 2.2.1 的设备上)

 @synthesize 123pig;
    - (IBAction)startClick:(id)sender{
    animationTimer = [NSTimer scheduledTimerWithTimeInterval:(1.00/30.00) target:self selector:@selector(tick) userInfo:nil repeats:NO];

        123pig.animationImages = [NSArray arrayWithObjects:
                                [UIImage imageNamed: @"123pigapple0001.png"],
                                 [UIImage imageNamed: @"123pigapple0002.png"],
                                 [UIImage imageNamed: @"123pigapple0003.png"],
                                 [UIImage imageNamed: @"123pigapple0004.png"],
                                  [UIImage imageNamed: @"123pigapple0005.png"],
                                  [UIImage imageNamed: @"123pigapple0006.png"],
                                  [UIImage imageNamed: @"123pigapple0007.png"],
                                  [UIImage imageNamed: @"123pigapple0008.png"],
                                  [UIImage imageNamed: @"123pigapple0009.png"],
                                  [UIImage imageNamed: @"123pigapple0010.png"],
                                  [UIImage imageNamed: @"123pigapple0011.png"],
                                  [UIImage imageNamed: @"123pigapple0013.png"],
                                  [UIImage imageNamed: @"123pigapple0014.png"],
                                  [UIImage imageNamed: @"123pigapple0015.png"],
                                  [UIImage imageNamed: @"123pigapple0016.png"],
                                  [UIImage imageNamed: @"123pigapple0017.png"],
                                  [UIImage imageNamed: @"123pigapple0018.png"],
                                  [UIImage imageNamed: @"123pigapple0019.png"],
                                  [UIImage imageNamed: @"123pigapple0020.png"],nil];

        [123pig setAnimationRepeatCount:1];
        123pig.animationDuration =.7;
        [123pig startAnimating];
}

    - (void)tick{
    [self animatePig];
}

    - (void)animatePig{

    UIImage *pigImage13=[UIImage imageNamed:@"123pigapple0020.png"];


    if(123pig.image == pigImage13)
        123pig.image = pigImage13;
    else
        123pig.image = pigImage13;






    }
    - (IBAction)startClick1:(id)sender{
    animationTimer1 = [NSTimer scheduledTimerWithTimeInterval:(1.00/30.00) target:self selector:@selector(tick1) userInfo:nil repeats:NO];
        123pig.animationImages = [NSArray arrayWithObjects:
                              [UIImage imageNamed: @"123pig0015.png"],
                              [UIImage imageNamed: @"123pig0016.png"],
                              [UIImage imageNamed: @"123pig0017.png"],
                              [UIImage imageNamed: @"123pig0018.png"],
                              [UIImage imageNamed: @"123pig0019.png"],
                              [UIImage imageNamed: @"123pig0020.png"],
                              [UIImage imageNamed: @"123pig0021.png"],
                              [UIImage imageNamed: @"123pig0022.png"],
                              [UIImage imageNamed: @"123pig0023.png"],
                              [UIImage imageNamed: @"123pig0024.png"],
                              [UIImage imageNamed: @"123pig0025.png"],
                              [UIImage imageNamed: @"123pig0026.png"],
                              [UIImage imageNamed: @"123pig0027.png"],
                              [UIImage imageNamed: @"123pig0028.png"],
                              [UIImage imageNamed: @"123pig0029.png"],
                              [UIImage imageNamed: @"123pig0030.png"],
                              [UIImage imageNamed: @"123pig0031.png"],
                              [UIImage imageNamed: @"123pig0032.png"],
                              [UIImage imageNamed: @"123pig0033.png"],
                              [UIImage imageNamed: @"123pig0034.png"],
                              [UIImage imageNamed: @"123pig0035.png"],
                              [UIImage imageNamed: @"123pig0036.png"],
                              [UIImage imageNamed: @"123pig0037.png"],
                              [UIImage imageNamed: @"123pig0038.png"],
                              [UIImage imageNamed: @"123pig0039.png"],
                              [UIImage imageNamed: @"123pig0040.png"],
                              [UIImage imageNamed: @"123pig0041.png"],
                              [UIImage imageNamed: @"123pig0042.png"],
                              [UIImage imageNamed: @"123pig0043.png"],
                              [UIImage imageNamed: @"123pig0044.png"],
                              [UIImage imageNamed: @"123pig0045.png"],
                              [UIImage imageNamed: @"123pig0046.png"],
                              [UIImage imageNamed: @"123pig0047.png"],
                              [UIImage imageNamed: @"123pig0048.png"],

                              nil];

    [123pig setAnimationRepeatCount:1];
    123pig.animationDuration =2.7;
    [123pig startAnimating];


      }
    - (void)tick1{
        [self animatePig1];
    }

    - (void) animatePig1{

        UIImage *pigImage11=[UIImage imageNamed:@"123pig0048.png"];


        if(123pig.image == pigImage11)
            123pig.image = pigImage11;
        else
            123pig.image = pigImage11;






    }
    - (void)stopTimer
    {
    [animationTimer invalidate];
    [animationTimer release];
    [animationTimer1 invalidate];
    [animationTimer1 release];
    }







    -(void) touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
    UITouch *touch = [[event allTouches] anyObject];
    CGPoint location = [touch locationInView:touch.view];
    123pig.center = location; 
    }

    - (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    }



    - (void)dealloc {
    [super dealloc];
    [123pig release];
    }
@end

我知道是 imageNamed 造成的,即使在内存警告之后,2.2.1 也不会清除它的缓存,在另一个 SO 问题上有人说“我的理解是 +imageNamed: 缓存应该尊重内存iPhone OS 3.0 上的警告。有机会时进行测试,如果发现不是这种情况,请报告错误。”现在,即使我确实下载了 3.0 的固件和 SDK,我也不知道它是否正在清除 imageNamed 的缓存,因为我无法在设备上对其进行测试!顺便说一句,在回答时请记住我是 iPhone sdk 的新手。提前致谢。

----------------编辑---------------- 我刚刚被苹果 iphone 开发者计划录取。 WOOOHOOO,我会检查 3.0 是否正确释放缓存的图像。

----------编辑------------------ 是的,它确实释放了缓存的图像。请在下面查看我的答案以获得进一步的说明。

【问题讨论】:

    标签: iphone


    【解决方案1】:

    好吧,看起来 iPhone OS 3.0 确实会在收到内存警告命令时清除缓存的图像,哇哦!我 1,Xcode 0。更多细节:在 iPhone os 2.2.1 中,当您发布动画图像视图时,缓存的图像不会被释放,因此如果您的应用程序有大量动画,那么最终 iPhone 会用完记忆并退出。所以你只需要使用其他更复杂的动画方法,如果可以避免的话,没有人愿意这样做。但是现在释放确实清除了缓存!我可以说,因为当我在我的应用程序中按下一个按钮来为视图设置动画时,需要等待一段时间才能播放动画,然后如果再次按下它就没有等待(因为它缓存了它)但是如果你按下另一个按钮为该视图设置动画,之前缓存的动画将被释放!所以按下第一个按钮会给你最初的等待,所以我现在可以放松并继续开发,而不是尝试修复归结为苹果错误的内存管理问题。

    【讨论】:

    • 您的释放代码不正确,可能会产生不释放 UIImageView 的副作用。
    【解决方案2】:

    我真的对你的计时器的行为感到困惑。您启动猪 UIImageView 动画,然后 1/30 秒后,您的计时器触发并将猪图像设置为其他内容?

    您可能希望合并这两种动画方法(UIImageView animationImages 和使用计时器的手动动画)。 UIImageView 真的不适合播放长动画(请参阅this question)。我认为它会在您启动动画时立即预加载所有图像 - 因此会占用大量内存。

    更好的选择可能是对所有事情都使用计时器并保持与当前帧相对应的局部变量。当您的计时器触发时,您可以使用 imageNamed: 仅加载一张图像并将其应用到 UIImageView。我不确定 UIImage 的缓存行为是什么,但我很确定将 100 个缓存行为放入 UIImageView 是一个坏主意。

    您是否也可以降低动画的帧速率?看来您正试图在 2.7 秒内翻阅猪动画中的所有 100 张图像 - 那是 37 fps! 24 fps 可能会很好,并且有助于减少内存占用。

    另外 - 这是题外话,但我注意到你在你的 dealloc 函数中调用 [123pig dealloc]。一般来说,你应该只调用release,如果对象的retain count为零(意味着不再使用对象),就会自动调用dealloc。手动调用它可能会导致您破坏应用程序中另一个对象仍在使用的东西。在这种情况下可能无关紧要,但在其他情况下可能会导致一些讨厌的错误。

    抱歉,我对缓存问题没有明确的答案。希望对您有所帮助!

    【讨论】:

    • 好的,感谢您的有用建议,但为了澄清一点,注释掉的代码毫无意义,我实际上只是为您在那里看到的帧数量设置动画。对 100 张图像进行动画处理是我最初的计划,但现在我不是,顺便说一下,计时器用于将动画的最后一帧设置为图像视图的图像。它似乎有效。
    【解决方案3】:

    您的 dealloc 代码不正确。您应该只释放 123pig,而不是释放它。您应该在调用[super dealloc] 之前这样做,因为在该调用之后,您的所有实例变量(包括 123pig)可能会失效。这可能表现为没有释放图像内存,因为存在对 123pig 的悬空引用。

    【讨论】:

    • 是的,另一位成员已经告诉我,我相应地编辑了我的代码,结果并不是问题所在。即使在内存警告之后,imageNamed 也没有释放它的缓存图像,这是导致问题的原因。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-07-06
    • 2018-12-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多