2012-06-01 58 views
6

我有4個方法,每個方法在方法返回前需要一兩秒鐘的時間,這些方法返回UIImage,我需要這些圖像以最快的方式顯示。最快的方式同時執行多個方法

-(NSMutableArray*)prepareImages{ 
    UIImage *imageToModifyUsingUIImageCategory; 

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

在上面的方法結束時,我將從該數組中得到4個圖像。每個「doSomethingAndReturn」方法需要一秒或兩秒鐘,這意味着我的prepareImages方法將約5秒鐘完成執行。太長了吧?

我的問題是,有什麼可以通過其他方式來完成所有這些更快? GCD是我的選擇嗎?怎麼樣?

任何幫助將不勝感激。謝謝!

回答

15

假設你不介意在後臺(而不是平行)加載圖像順序,一個簡單的派遣背景隊列運行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來運行它們全部。這需要更多的努力才能實施。如果一次處理多個大圖像,請注意內存使用情況。

+0

謝謝,我正在考慮將doSomethingAndReturn方法轉換爲NSOperation,但我很懷疑嘗試一下。但我會盡力做出努力,因爲你只是推我:)順便說一句,使用gcd與doSomethingAndReturn而不是NSOperation?我想gcd更優雅,但你認爲我可以用它做到嗎?謝謝! – janusbalatbat

+2

您可以將每個單獨的調用包裝在自己的dispatch_async中,以使它們全部並行運行。要等待他們完成,您可以創建一個調度組。請參閱此處的文檔:http://developer.apple.com/library/ios/documentation/General/Conceptual/ConcurrencyProgrammingGuide/OperationQueues/OperationQueues.html#//apple_ref/doc/uid/TP40008091-CH102-SW25 –

+0

非常感謝非常感謝...幫了我很多。 –

1

我有一個想法如何解決,但尚未測試。我從我遇到並解決其他一些問題繪圖解決方案:

  • 插入NSNullNSMutableArray用作佔位符。
  • dispatch_async繁重的工作並替換NSMutableArray相應的條目(使用@synchronized關鍵字鎖定NSMutableArray
  • 同樣在dispatch async功能,調度回到主隊列中的函數來更新視圖。
+0

感謝您的迴應!將嘗試解決,只要我碰我的Mac。 – janusbalatbat

1

你可以使用一個NSOperationQueue

的NSOperationQueue類調節一組的NSOperation對象的執行。在添加到隊列後,操作將保留在該隊列中,直到它被明確取消或完成其任務。隊列中的操作(但尚未執行)本身根據優先級和操作間對象依賴性進行組織,並相應執行。應用程序可能會創建多個操作隊列並將操作提交給它們中的任何一個。

example for a NSOperationQueue imeplementation

GCD Queue

大中央調度(GCD)調度隊列是用於執行任務的有力工具。調度隊列讓你可以與調用者異步或同步地執行任意代碼塊。您可以使用分派隊列來執行幾乎所有用於在單獨的線程上執行的任務。調度隊列的優點是它們比相應的線程代碼更簡單,更有效地執行這些任務。

example for a GCD Queue implementation

1

您可以在同一時間對做你的處理器的另一個核心是試圖執行:

​​

如果您的處理器有四個核心每種方法將在一個不同的核心執行。

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個想法:串行是沒有必要的。