6

私は 4 つのメソッドを持っています。各メソッドは、メソッドが戻るまでに 1 ~ 2 秒かかります。これらのメソッドは UIImage を返します。これらの画像を最速で表示するには、これらの画像が必要です。

-(NSMutableArray*)prepareImages{
  UIImage *imageToModifyUsingUIImageCategory;

  NSMutableArray *imageArray = [[NSMutableArray alloc]initWithObjects:
  [imageToModifyUsingUIImageCategory doSomethingAndReturn1],
  [imageToModifyUsingUIImageCategory doSomethingAndReturn2],
  [imageToModifyUsingUIImageCategory doSomethingAndReturn3],
  [imageToModifyUsingUIImageCategory doSomethingAndReturn4],nil];    
  return imageArray;
}

上記の方法の最後に、その配列から 4 つの画像が得られます。各「doSomethingAndReturn」メソッドには 1 ~ 2 秒かかります。これは、prepareImagesメソッドの実行が約 5 秒で終了することを意味します。長すぎるでしょ?

私の質問は、これらすべてをより速く達成するための他の方法は何でしょうか? GCD は私のオプションですか? どうやって?

どんな助けでも大歓迎です。ありがとう!

4

5 に答える 5

16

画像を (並列ではなく) バックグラウンドで順番にロードすることを気にしないと仮定すると、実行するバックグラウンド キューへの単純なディスパッチでprepareImagesうまくいきます。

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{
    NSArray *images = [self prepareImages];

    // now send the result back to the main thread so we can do
    // UIKit stuff
    dispatch_async(dispatch_get_main_queue(), ^{
        // set the images on your UIImageViews here...
    });
});

これにより、優先度の低いバックグラウンド キューに画像が読み込まれ、処理が完了するとメイン スレッドにディスパッチされます。

この優先度をさらに低くしたい場合は、 を使用できますがDISPATCH_QUEUE_PRIORITY_BACKGROUND、これは iOS 4.3 以降でのみ使用できます。この場合の戻り値を確認する必要があります。戻り値dispatch_get_global_queueが 0 の場合は、他の優先度のいずれかにフォールバックできます。

各画像を並行してロードする場合は、おそらくdoSomethingAndReturnメソッドをNSOperationサブクラスに変換し、NSOperationQueueそれらすべてを実行するために an を使用する必要があります。それを実装するには、もう少し努力が必要です。複数の大きな画像を一度に処理する場合は、メモリの使用にも注意してください。

于 2012-06-01T09:48:28.957 に答える
1

プロセッサの別のコアで同時に実行して、次のことを試してください。

NSThread detachNewThreadSelector:@selector(YOUR_METHODS_HERE:) toTarget:self withObject:nil];
NSThread detachNewThreadSelector:@selector(YOUR_METHODS_HERE:) toTarget:self withObject:nil];
NSThread detachNewThreadSelector:@selector(YOUR_METHODS_HERE:) toTarget:self withObject:nil];
NSThread detachNewThreadSelector:@selector(YOUR_METHODS_HERE:) toTarget:self withObject:nil];

プロセッサに 4 つのコアがある場合、各メソッドは異なるコアで実行されます。

于 2012-06-01T09:57:24.030 に答える
1

NSOperationQueueを使用できます:

NSOperationQueue クラスは、一連の NSOperation オブジェクトの実行を規制します。キューに追加された操作は、明示的に取り消されるか、そのタスクの実行が終了するまで、そのキューに残ります。キュー内の (まだ実行されていない) 操作は、優先度レベルと操作オブジェクト間の依存関係に従って編成され、それに応じて実行されます。アプリケーションは、複数の操作キューを作成し、それらのいずれかに操作を送信できます。

NSOperationQueue 実装の例

またはGCD Queue :

Grand Central Dispatch (GCD) ディスパッチ キューは、タスクを実行するための強力なツールです。ディスパッチ キューを使用すると、任意のコード ブロックを呼び出し元に対して非同期または同期で実行できます。ディスパッチ キューを使用すると、個別のスレッドで実行していたほとんどすべてのタスクを実行できます。ディスパッチ キューの利点は、対応するスレッド化されたコードよりも使いやすく、これらのタスクをはるかに効率的に実行できることです。

GCD Queue 実装の例

于 2012-06-01T09:46:07.523 に答える
0

私は演習としてそれを行います。doSomethingAndReturnごとにGCD同時Qを使用し、シリアルqを使用してコールバックの数を監視します。コールバックの数がdoSomethingAndReturn(s)の数と等しい場合、prepareImages配列を返します。

コンセプトをテストするためのコードを作成しました。

-(NSString *)doSomethingAndReturn1
{
    for (int i=0; i<30; i++) 
    {
        NSLog(@"soSomethingAndReturn1 i: %i", i);
    }
    return @"soSomethingAndReturn1";
}

-(NSString *)doSomethingAndReturn2
{
    for (int i=0; i<10; i++) 
    {
        NSLog(@"soSomethingAndReturn2 i: %i", i);
    }
    return @"soSomethingAndReturn2";
}

-(NSString *)doSomethingAndReturn3
{
    for (int i=0; i<20; i++) 
    {
        NSLog(@"soSomethingAndReturn3 i: %i", i);
    }
    return @"soSomethingAndReturn3";
}

-(void)addToArray:(NSString *)str
{
    [asyncArray addObject:str];
    NSLog(@"asyncArray: %@", asyncArray);
}

- (IBAction)buttonMultitasksPressed:(id)sender 
{
    dispatch_queue_t serialdQueue;
    serialdQueue = dispatch_queue_create("com.mydomain.testbed.multimethods", NULL);
        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
            [self addToArray:[self doSomethingAndReturn1]];
        });
        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
            [self addToArray:[self doSomethingAndReturn2]];
        });
        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
            [self addToArray:[self doSomethingAndReturn3]];
        });
        dispatch_sync(serialdQueue, ^{
            while (!([asyncArray count] == 3)) 
            {
                NSLog(@"not there yet count: %i", [asyncArray count]);
            }
        });

    NSLog(@"end of dispatch_sync serialQueue");
//    return asyncArray;
}

編集:2番目の考え:シリアルは必要ありません。

于 2012-06-01T14:22:02.633 に答える