目标c-for循环以从iCloud顺序获取图像

时间:2019-04-22 17:32:48

标签: objective-c asynchronous

在IOS上,我需要获取一组选定图像的元数据。但是,由于图像已备份到iCloud,因此有时可能会立即返回(缓存),有时可能需要一两秒钟。

for循环快速运行,我可以等待所有图像被处理后再前进。但是它们仍然是并行获取的。如何通过等待块完成然后再移至下一张图像来使for循环顺序运行。

// Step 4: Fetch Details like Metadata for this batch
-(void) getDetailsForThisBatchOfNewAssets:(NSMutableArray*) mArrBatchOfNewAssets
                    withCompletionHandler:(blockReturnsMArrAndMArr) blockReturns{

    NSLog(@"%s with arraySize of %lu",__PRETTY_FUNCTION__, (unsigned long)[mArrBatchOfNewAssets count] );

    long assetCount = [mArrBatchOfNewAssets count];

    NSMutableArray *mArrNewAssetsAndDetails = [[NSMutableArray alloc] init];
    NSMutableArray *mArrNewAssetFailed = [[NSMutableArray alloc] init];

    if(assetCount == 0){

        NSLog(@" Looks like there are no NEW media files on the device.");
        return;
    }
    else
        NSLog(@"found %ld assets in all that need to be backed up", assetCount);

    dispatch_group_t groupForLoopGetDetails = dispatch_group_create();

    for(long i = 0 ; i < assetCount; i++){

        PHAsset *currentAsset = [[mArrBatchOfNewAssets objectAtIndex:i] objectForKey:@"asset"];

        NSString *mediaIdentifier = [[[currentAsset localIdentifier] componentsSeparatedByString:@"/"] firstObject];
        [mArrIdentifiersInThisBatch addObject:mediaIdentifier];

        dispatch_group_enter(groupForLoopGetDetails);

        [mediaManager getDetailedRecordForAsset:currentAsset
                  withCompletionHandler:^(NSMutableDictionary *mDicDetailedRecord, NSMutableDictionary *mDicRecordForError)
        {
              if(mDicRecordForError[@"error"]){
                  [mArrNewAssetFailed addObject:mDicRecordForError];

                  NSLog(@"Position %ld - Failed to fetch Asset with LocalIdentifier: %@, adding it to Failed Table. Record: %@",i,[currentAsset localIdentifier], mDicRecordForError);

              } else {
                  [mArrNewAssetsAndDetails addObject:mDicDetailedRecord ];

                  NSLog(@"Position %ld - added asset with LocalIdentifier to mArrNewAssetsAndDetails %@",i,[currentAsset localIdentifier]);
              }

            dispatch_group_leave(groupForLoopGetDetails);
        }];
    }   // end of for loop that iterates through each asset.

    dispatch_group_notify(groupForLoopGetDetails, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{

        NSLog(@"Completed gathering details for this batch of assets for backup. Count : %lu and failed Media count: %lu",(unsigned long)[mArrNewAssetsAndDetails count], (unsigned long)[mArrNewAssetFailed count]);

            blockReturns(mArrNewAssetsAndDetails,mArrNewAssetFailed);
    });

}

我已经浏览了关于此主题的几个问题,但仍然没有弄清楚如何使它按顺序运行。

我不想为此方法进行“自我调用”,因为在达到此方法之前,我已经在另一个地方进行了“自我调用”,并且我的代码现在正越来越多地被通知和捕获,因为

1 个答案:

答案 0 :(得分:0)

假设getDetailedRecordForAsset的完成处理程序在另一个线程上调用,则可以在循环内使用信号量阻止执行(注意:不要在主线程上执行此操作)在等待完成处理程序时。

然后在循环内删除调度组的内容:

  • 在调用getDetailedRecordForAsset之前创建信号量,如下所示:dispatch_semaphore_t semaphore = dispatch_semaphore_create( 0);

  • 作为完成处理程序调用{​​{1}}

  • 的最后一条语句
  • 在调用dispatch_semaphore_signal( semaphore);之后立即使用getDetailedRecordForAsset

  • 等待完成处理程序的结束

因此循环的结构如下:

dispatch_semaphore_wait( semaphore, DISPATCH_TIME_FOREVER);