2

我们将大约 30 个完整的 320 x 480 图像加载到动画数组中。这些图像非常小,每张图像大约 5 - 7Kb。问题是当我们运行循环来填充图像数组时,它似乎会在填充该数组时暂停整个应用程序。有没有办法在一个单独的线程中加载这个带有图像的可变数组,或者让数组在不影响性能的情况下填充?谢谢

    NSMutableArray *totalAnimationImages  = [[NSMutableArray alloc] initWithCapacity:numOfImages];

for(int i = 1; i < numOfImages; i++) {
    [totalAnimationImages addObject:[UIImage imageNamed:
                                     [NSString stringWithFormat:@"%@%d.png", image, i]]];
}

annImage.animationImages = totalAnimationImages;
annImage.animationDuration = speed; //.4 second
annImage.animationRepeatCount = 1; //infinite loop

[annImage startAnimating]; //start the animation

[totalAnimationImages release];

在处理此问题时,并使用 shabzco 提供的线程建议,我提出了以下代码来处理循环,更改图像视图中的图像,似乎完全没有性能影响。这一次只保存一个图像,而不是 NSMutableArray 中的 30 个。正如 Richard J. Ross III 所说,一旦动画开始,它就会将所有图像“处理成内存中的位图格式”。这就是漫长的等待/滞后的来源。在下面的代码中,每次图像更新只发生一次,而不是启动动画时发生 30 次。我在建议的调度线程中使用带计时器的 while 循环来防止此计时器影响主线程,从而可能在动画期间产生不稳定的性能。请提供有关此解决方案的反馈!谢谢

更新:Shabzco 建议我将“ImageNamed”替换为“imageWithContentsOfFile”以避免由于 ImageNamed 可能在内存中缓存图像而导致的奇怪内存泄漏。这是在运行 xcode profiler 并观察“Real Memory”计数器后发现的。很明显,每次动画运行时,实际内存都会越来越多,直到最终应用程序崩溃。用“imageWithContentsOfFile”替换“ImageNamed”后,问题就消失了。我已经更新了下面的代码。

annImage.image = [UIImage imageNamed:@""];
[annImage setAlpha:1.0];
dispatch_queue_t concurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(concurrentQueue, ^{ 
    NSTimeInterval timeout = 1.00 / speed;   // Number of seconds before giving up
    NSTimeInterval idle = 1.00 / 8;     // Number of seconds to pause within loop
    BOOL timedOut = NO;
    NSDate *timeoutDate;
    for(int i = 1; i < numOfImages; i++) {
        timeoutDate = [[NSDate alloc] initWithTimeIntervalSinceNow:timeout];
        timedOut = NO;
        while (!timedOut)
        {
            NSDate *tick = [[NSDate alloc] initWithTimeIntervalSinceNow:idle];
            [[NSRunLoop currentRunLoop] runUntilDate:tick];
            timedOut = ([tick compare:timeoutDate] == NSOrderedDescending);
            [tick release];
        }
        dispatch_async(dispatch_get_main_queue(), ^{
            //annImage.image = [UIImage imageNamed:
            //                      [NSString stringWithFormat:@"%@%d.png", image, i]];
            NSString *filePath = [[NSBundle mainBundle] pathForResource:[NSString stringWithFormat:@"%@%d", image, i] ofType:@"png"];
            annImage.image = [UIImage imageWithContentsOfFile:filePath];
        });   
    }

    dispatch_async(dispatch_get_main_queue(), ^{
        [UIView beginAnimations:nil context:nil];
        [UIView setAnimationDuration: 0.3];
        [annImage setAlpha:0.0];
        [UIView setAnimationCurve:UIViewAnimationCurveEaseOut];
        [UIView commitAnimations];

    });
});
4

1 回答 1

1

这将使您的 for 循环发生在不同的线程中,并在所有内容加载后开始动画。

@autoreleasepool {
        NSMutableArray *totalAnimationImages  = [[NSMutableArray alloc] initWithCapacity:numOfImages];
        dispatch_queue_t concurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
        dispatch_async(concurrentQueue, ^{   
            for(int i = 1; i < numOfImages; i++) {
                [totalAnimationImages addObject:[UIImage imageNamed:
                                                 [NSString stringWithFormat:@"%@%d.png", image, i]]];
            }
            annImage.animationImages = totalAnimationImages;
            annImage.animationDuration = speed; //.4 second
            annImage.animationRepeatCount = 1; //infinite loop
            [annImage startAnimating]; //start the animation
            dispatch_async(dispatch_get_main_queue(), ^{

                [totalAnimationImages release];

            });
        });
}
于 2012-07-06T15:08:11.613 回答