Подтвердить что ты не робот

Подождите, пока блоки объекта assetForURL будут завершены

Я хотел бы подождать, пока этот код будет выполнен до продолжения, но поскольку эти блоки называются assynchronously, я не знаю, как это сделать.

NSURL *asseturl;
NSMutableArray *tmpListAsset = [[NSMutableArray alloc] init];

ALAssetsLibrary *library = [[[ALAssetsLibrary alloc] init] autorelease];
NSMutableArray *objectsToRemove = [[NSMutableArray alloc] init];
for (NSDictionary *dico in assetsList) {
    asseturl = [NSURL URLWithString:[dico objectForKey:@"assetUrl"]];
    NSLog(@"asset url %@", asseturl);
    // Try to load asset at mediaURL
    [library assetForURL:asseturl resultBlock:^(ALAsset *asset) {
        // If asset doesn't exists
        if (!asset){
            [objectsToRemove addObject:dico];
        }else{
            [tmpListAsset addObject:[asseturl absoluteString]];
            NSLog(@"tmpListAsset : %@", tmpListAsset);
        }
    } failureBlock:^(NSError *error) {
        // Type your code here for failure (when user doesn't allow location in your app)
    }];
}
4b9b3361

Ответ 2

Семафор GCD:

dispatch_semaphore_t sema = dispatch_semaphore_create(0);
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0);

for (NSURL *url in self.assetUrls) {
    dispatch_async(queue, ^{
        [library assetForURL:url resultBlock:^(ALAsset *asset) {
            [self.assets 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 */
NSLog(@"%@", self.assets);

Ответ 3

Обратите внимание, что assetForURL: resultBlock: failureBlock: будет зависеть, если основной поток ожидает без запуска RunLoop. Это альтернативное решение (чище:-)):

#import <libkern/OSAtomic.h>

...

ALAssetsLibrary *library;
NSMutableArray *assets;
...
__block int32_t counter = 0;
for (NSURL *url in urls) {
    OSAtomicIncrement32(&counter);
    [library assetForURL:url resultBlock:^(ALAsset *asset) {
        if (asset)
            [assets addObject:asset];
        OSAtomicDecrement32(&counter);
    } failureBlock:^(NSError *error) {
        OSAtomicDecrement32(&counter);
    }];
}
while (counter > 0) {
    [[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.01]];
}

Ответ 4

Самое простое - переместить свой код внутрь (в конце) resultBlock или failureBlock. Таким образом, ваш код будет работать в правильном порядке, и вы также сохраните асинхронное поведение.

Ответ 5

Это простой способ сделать это. Может быть, не такой элегантный, как использование GCD, но он должен выполнить эту работу... Это сделает ваш метод блокировкой вместо неблокирования.

__block BOOL isFinished = NO;
NSURL *asseturl;
NSMutableArray *tmpListAsset = [[NSMutableArray alloc] init];

ALAssetsLibrary *library = [[[ALAssetsLibrary alloc] init];
NSMutableArray *objectsToRemove = [[NSMutableArray alloc] init];
for (NSDictionary *dico in assetsList) {
    asseturl = [NSURL URLWithString:[dico objectForKey:@"assetUrl"]];
    NSLog(@"asset url %@", asseturl);
    // Try to load asset at mediaURL
    [library assetForURL:asseturl resultBlock:^(ALAsset *asset) {
        // If asset doesn't exists
        if (!asset){
            [objectsToRemove addObject:dico];
        }else{
            [tmpListAsset addObject:[asseturl absoluteString]];
            NSLog(@"tmpListAsset : %@", tmpListAsset);
        }
        if (objectsToRemove.count + tmpListAsset.count == assetsList.count) {
            isFinished = YES;
        }
    } failureBlock:^(NSError *error) {
        // Type your code here for failure (when user doesn't allow location in your app)
        isFinished = YES;
    }];
}

while (!isFinished) {
    [[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.01f]];
}