2

約30枚の完全な320x480画像をアニメーション配列にロードしています。これらの画像のサイズは非常に小さく、画像あたり約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ではなく、一度に1つの画像のみを保持します。リチャードJ.ロスIIIが言ったように、アニメーションが開始されるとすぐに、すべての画像が「メモリ内のビットマップ形式に」処理されます。これが長い待ち時間/遅れの原因です。以下のコードでは、これはアニメーションを開始するためだけに30ではなく、画像の更新ごとに1回だけ発生します。提案されたディスパッチスレッドでタイマー付きのwhileループを使用して、このタイマーがメインスレッドに影響を与えないようにし、アニメーション中にぎくしゃくしたパフォーマンスを作成する可能性があります。このソリューションに関するフィードバックを提供してください。ありがとう

更新:Shabzcoは、ImageNamedがメモリに画像をキャッシュする可能性があることによる奇妙なメモリリークを回避するために、「ImageNamed」を「imageWithContentsOfFile」に置き換えることを提案しました。これは、xcodeプロファイラーを実行して「RealMemory」カウンターを監視した後に発見されました。アニメーションが実行されるたびに、最終的にアプリがクラッシュするまで、実際のメモリがますます増加することが明らかになりました。「ImageNamed」を「imageWithContentsOfFile」に置き換えた後、問題は解決しました。以下のコードを更新しました。

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 に答える