2015-04-12 5 views
1

Я использую generateCGImagesAsynchronouslyForTimes, чтобы сделать некоторые изображения и сохранить их в NSMutableArray, теперь, когда заканчивается функция generateCGImagesAsynchronouslyForTimes, я хочу использовать изображение в этом массиве, как я могу получить код, который я хочу вывести после того, как все изображения были сгенерированы для завершения. Я бы просто поместил его в блок кода completionHandler, но я не хочу, чтобы он запускался несколько раз. Я просто хочу запустить его один раз, после того, как этот метод завершился.Подождите, пока метод Xcode закончит

EDIT

Это все внутри - (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. Я нахожусь на телефоне, поэтому код очень не очень хорошо. Раздел в прочитанном мне называется «Задачи в параллельном режиме». Он покажет вам, как создать массив задач, а затем иметь один обработчик завершения, как только весь массив завершит обработку. – Fogmeister

+0

Может ли нижестоящий избиратель оставить комментарий, чтобы объяснить, почему мой ответ неверен? Или они просто трусливы? – Fogmeister

2

Предполагая, что generateCGImagesAsynchronouslyForTimes:completionHandler: называет свои обработчики завершения последовательно (что кажется разумным, но документы явно не обещают), то это очень просто. Просто установите переменную __block на счет вашего times и уменьшите его один раз за завершение. Когда он равен нулю, вызовите другую функцию.

__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); 
    } 
}];