我有一个列表ALAsset URL的数组。我想将该URL逐个转换为ALAsset并将其添加到新数组中。
这是我的代码:
-(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 :(得分:1)
我找到了问题的答案:
-(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];
}
});
}
答案 1 :(得分: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]);
}
];
}
});
}
答案 2 :(得分:0)
尽管日志语句在任何结果块保证运行之前运行,但您的代码已设法通过外观恢复四个资产。
结果块是异步调用的,这意味着在任何资产实际放入retrievedAssetArray
之前,您可以轻松地退出for循环。然后在主队列上执行NSLog。
您需要重构代码以计算结果块的执行次数,并在计数达到assetsArray
中的对象数时调度到主队列。您需要检查结果块中的 。
答案 3 :(得分: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:
,您都需要等到它完成执行。
您可以等待异步操作完成使用dispatch_group
或dispatch_semaphore
或减少异步操作次数的简单块,并在达到零时调用完成。