2014-12-10 2 views
0

У меня есть массив списка ALAsset URL. Я хочу преобразовать этот URL в ALAsset один за другим и добавить его в новый массив.NSMutableArray addObject в блоке дает нулевой массив

Вот мой код:

-(void)retrieveAssetsWithArray:(NSArray *)assetsArray 
{ 

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 
     // Background work 
     __block NSMutableArray *retrievedAssetsArray = [[NSMutableArray alloc] init]; 
     for (int i = 0; i < [assetsArray count]; i++) 
     { 
      ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init]; 
      [library assetForURL:[NSURL URLWithString:[assetsArray objectAtIndex:i]] 
        resultBlock:^(ALAsset *asset) 
      { 
       if (asset) 
       { 
        NSLog(@"assetss: %@", asset); 
        [retrievedAssetsArray addObject:asset]; 
        NSLog(@"assets arayyyy: %@", retrievedAssetsArray); 
       } 
      } 
      failureBlock:^(NSError *error) 
      { 
       NSLog(@"Error: Cannot load asset - %@", [error localizedDescription]); 
      } 
      ]; 
     } 

     dispatch_async(dispatch_get_main_queue(), ^{ 
      // Update UI 
      if ([self.delegate respondsToSelector:@selector(getRetrievedAssetsFromPhotoLibrary:)]) 
      { 
       NSLog(@"retrievedAssetsArray :%@", retrievedAssetsArray); 
       [self.delegate getRetrievedAssetsFromPhotoLibrary:retrievedAssetsArray]; 
      } 
     }); 
    }); 
} 

Часть преобразовать URL в ALAsset работает нормально. Но retrievedAssetsArray возвращается, как это, когда я пытаюсь его регистрации в dispatch_async(dispatch_get_main_queue():

retrievedAssetsArray :(
    "ALAsset - Type:Unknown, URLs:(null)", 
    "ALAsset - Type:Unknown, URLs:(null)", 
    "ALAsset - Type:Unknown, URLs:(null)", 
    "ALAsset - Type:Unknown, URLs:(null)" 
) 

Почему это происходит? Может кто-нибудь, пожалуйста, скажите мне, как я могу это исправить? Приветствия.

+0

не могу вам сказать много без источника для 'getRetrievedAssetsFromPhotoLibrary'. –

ответ

0

Я нашел ответ на мой вопрос:

-(void)retrieveAssetsWithArray:(NSArray *)assetsArray 
{ 
    __block NSMutableArray *retrievedAssetsArray = [[NSMutableArray alloc] init]; 
    dispatch_semaphore_t sema = dispatch_semaphore_create(0); 
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0); 
    ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init]; 

    for (NSString *string in assetsArray) { 
     dispatch_async(queue, ^{ 
      [library assetForURL:[NSURL URLWithString:string] resultBlock:^(ALAsset *asset) { 
       [retrievedAssetsArray addObject:asset]; 
       dispatch_semaphore_signal(sema); 
      } failureBlock:^(NSError *error) { 
       dispatch_semaphore_signal(sema); 
      }]; 
     }); 

     dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER); 
    } 

    dispatch_release(sema); 

    /* Check out ALAssets and return in delegate methods*/  
    dispatch_async(dispatch_get_main_queue(), ^{ 
     // Update UI 
     if ([self.delegate respondsToSelector:@selector(getRetrievedAssetsFromPhotoLibrary:)]) 
     { 
      NSLog(@"retrieve %@", retrievedAssetsArray); 
      [self.delegate getRetrievedAssetsFromPhotoLibrary:retrievedAssetsArray]; 
     } 
    }); 

} 
0

Вы должны сделать это, как там:

typedef void (^VoidBlock)(void); 

-(void)retrieveAssetsWithArray:(NSArray *)assetsArray 
{ 

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 
     // Background work 
     __block NSMutableArray *retrievedAssetsArray = [[NSMutableArray alloc] init]; 


     __block NSNumber *completCount = @0; 
     VoidBlock internalCompletionBlock = ^{ 
      completCount = @(completCount.integerValue + 1); 

      if (completCount.integerValue != assetsArray.count) 
       return; 

      dispatch_async(dispatch_get_main_queue(), ^{ 
       // Update UI 
       if ([self.delegate respondsToSelector:@selector(getRetrievedAssetsFromPhotoLibrary:)]) 
       { 
        NSLog(@"retrievedAssetsArray :%@", retrievedAssetsArray); 
        [self.delegate getRetrievedAssetsFromPhotoLibrary:retrievedAssetsArray]; 
       } 
      }); 
     }; 


     for (int i = 0; i < [assetsArray count]; i++) 
     { 
      ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init]; 
      [library assetForURL:[NSURL URLWithString:[assetsArray objectAtIndex:i]] 
        resultBlock:^(ALAsset *asset) 
      { 
       if (asset) 
       { 
        NSLog(@"assetss: %@", asset); 
        [retrievedAssetsArray addObject:asset]; 
        NSLog(@"assets arayyyy: %@", retrievedAssetsArray); 
       } 
       internalCompletionBlock(); 

      } 
        failureBlock:^(NSError *error) 
      { 
       internalCompletionBlock(); 
       NSLog(@"Error: Cannot load asset - %@", [error localizedDescription]); 
      } 
      ]; 
     } 
    }); 
} 
0

Ваш код удалось отступить четыре активов от взглядов вещей, несмотря на то, что утверждение журнала выполняется перед любым из результирующих блоков гарантированно иметь запустить.

Блок результатов вызывается асинхронно, что означает, что вы можете легко выйти из цикла for, прежде чем какой-либо из активов действительно будет помещен в retrievedAssetArray. Затем вы выполняете NSLog в главной очереди.

Вам необходимо реорганизовать код, чтобы подсчитать количество выполненных блоков результатов и выполнить отправку в основную очередь, когда количество достигло числа объектов в assetsArray. Вам нужно сделать эту проверку внутри блок результатов.

0

В качестве части проблемы вы должны сохранить ALAssetLibrary на весь период асинхронного assetForURL:resultBlock:failureBlock:.

Таким образом, вы могли бы рассмотреть, чтобы организовать одноэлементный экземпляр для ALAssetLibrary, например:

static ALAssetsLibrary* library; 
static dispatch_once_t predicate; 
dispatch_once(&predicate, ^{ 
    ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init]; 
}); 

Основная проблема заключается в том, что assetForURL:resultBlock:failureBlock: асинхронный метод, так что вы должны ждать, пока он не закончит выполнение ли путем вызова resultBlock: или failureBlock: ,

Вы можете дождаться завершения операций async с помощью dispatch_group или dispatch_semaphore или простого блока, который уменьшает количество операций async и завершает вызов, когда он достигнет нуля.