2015-04-12 112 views
1

我使用generateCGImagesAsynchronouslyForTimes做出一些圖像,並將它們保存到NSMutableArray,現在當函數generateCGImagesAsynchronouslyForTimes結束我希望這個陣列中使用的圖像,我怎麼能有代碼我想exectue畢竟所有的圖像已經生成完成。我只是把它放在completionHandler的代碼塊中,但我不希望它運行多次,我只是想在這個方法結束後運行一次。等待Xcode的方法來完成

編輯

這是所有裏面- (BFTask *)createImage:(NSInteger)someParameter {

AVAssetImageGenerator *imageGenerator = [AVAssetImageGenerator assetImageGeneratorWithAsset:passsedAsset]; 
[imageGenerator generateCGImagesAsynchronouslyForTimes:times 
            completionHandler:^(CMTime requestedTime, CGImageRef image, CMTime actualTime, 
                 AVAssetImageGeneratorResult result, NSError *error) { 
    if (result == AVAssetImageGeneratorSucceeded) { 
     UIImage *img = [UIImage imageWithCGImage:image]; 
     NSData *imgData = UIImageJPEGRepresentation(img, 1.0); 
     UIImage *saveImage = [[UIImage alloc] initWithData:imgData]; 
     [mutaleArray addObject:saveImage]; 
     //I get Assigment to read only property error on line below 
     completionSource.task = saveImage; 
    } 
]}; 

什麼,我應該將其賦值給?

回答

3

我會首先考慮的兩種方法是NSOperationQueue(您可以檢測它何時爲空)或使用Bolts框架的更容易的選擇。

螺栓允許你創建一個異步運行的任務數組,然後一旦它們完成,它就會進入下一個位。

讓我得到一個鏈接...

在這裏你去... https://github.com/BoltsFramework

你還可以通過的CocoaPods這讓一切更容易得到這個。

的螺栓是如何工作的一個例子...

此刻,你將有異步創建圖像的功能。喜歡的東西... - (UIImage *)createImage: (id)someParameter;現在好了,你可以做到這一點...

- (BFTask *)createImage:(NSInteger)someParameter 
{ 
    BFTaskCompletionSource *completionSource = [BFTaskCompletionSource taskCompletionSource]; 

    //create your image asynchronously and then set the result of the task 

    someAsyncMethodToCreateYourImageWithACompletionBlock...^(UIImage *createdImage){ 
     // add the images here... 
     [self.imageArray addObject:createdImage]; 

     // the result doesn't need to be the image it just informs 
     // that this one task is complete. 
     completionSource.result = createdImage; 
    } 
    return completionSource.task; 
} 

現在你必須並行運行的任務...

- (void)createAllTheImagesAsyncAndThenDoSomething 
{ 
    // create the empty image array here 
    self.imageArray = [NSMutableArray array]; 

    NSMutableArray *tasks = [NSMutableArray array]; 
    for (NSInteger i=0 ; i<100 ; ++i) { 
     // Start this creation immediately and add its task to the list. 
     [tasks addObject:[self createImage:i]]; 
    } 
    // Return a new task that will be marked as completed when all of the created images are finished. 
    [[BFTask taskForCompletionOfAllTasks:tasks] continueWithBlock:^id(BFTask *task){ 
     // this code will only run once all the images are created. 
     // in here self.imageArray is populated with all the images. 
    } 
} 
+0

感謝發佈,我沒有投票順便說一句,但你會詳細說明如何使用螺栓 – iqueqiorio

+0

檢查GitHub鏈接。我在我的手機atm,所以不能做得很好。閱讀我的部分被稱爲「並行任務」。它將向您展示如何創建一個任務數組,然後在整個數組完成處理後擁有一個完成處理程序。 – Fogmeister

+0

下來的選民請留下評論,解釋爲什麼我的答案是不正確的?還是他們只是懦弱? – Fogmeister

2

假設generateCGImagesAsynchronouslyForTimes:completionHandler:依次調用其完成處理(這似乎是合理的,但文件沒有明確承諾),那麼這很簡單。只需將__block變量設置爲您的times的計數並在完成時將其減1。當它爲零時,請致電您的其他功能。

__block NSInteger count = [times count]; 
    [imageGenerator generateCGImagesAsynchronouslyForTimes:times 
            completionHandler:^(CMTime requestedTime, CGImageRef image, CMTime actualTime, 
                 AVAssetImageGeneratorResult result, NSError *error) { 

     ... Do all the stuff ... 
     if (--count <= 0) { 
      finalize() 
     } 

如果generateCGImagesAsynchronouslyForTimes:實際上做並行工作,因此可以稱之爲完成處理並行,那麼你就可以處理所有這些與調度組。

dispatch_group_t group = dispatch_group_create(); 

// 
// Enter the group once for each time 
// 
[times enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { 
    dispatch_group_enter(group); 
}]; 

// 
// This local variable will be captured, so you don't need a property for it. 
// 
NSMutableArray *results = [NSMutableArray new]; 

// 
// Register a block to fire when it's all done 
// 
dispatch_group_notify(group, dispatch_get_main_queue(), ^{ 
    NSLog(@"Whatever you want to do when everything is done."); 
    NSLog(@"results is captured by this: %@", results); 
}); 

AVAssetImageGenerator *imageGenerator = [AVAssetImageGenerator assetImageGeneratorWithAsset:nil]; 
[imageGenerator generateCGImagesAsynchronouslyForTimes:times 
            completionHandler:^(CMTime requestedTime, CGImageRef image, CMTime actualTime, 
                 AVAssetImageGeneratorResult result, NSError *error) 
{ 
    if (result == AVAssetImageGeneratorSucceeded) { 
     // 
     // Create saveImage 
     // 
     id saveImage = @""; 

     // 
     // Update external things on a serial queue. 
     // You may use your own serial queue if you like. 
     // 
     dispatch_sync(dispatch_get_main_queue(), ^{ 
      [results addObject:saveImage]; 
     }); 

     // 
     // Signal we're done 
     // 
     dispatch_group_leave(group); 
    } 
}];