2015-04-12 109 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); 
    } 
}];