Код застрял при запросе свойства размера ALAssetRepresentation
У меня есть метод, который возвращает данные ALAsset. Я вызываю этот метод для одного актива за другим, чтобы получить от них NSData и загрузить его на сервер. После каждых 4 или 5 вызовов код застревает при вызове rep.size ниже. Когда я приостанавливаю и возобновляю выполнение в XCode, оно снова начинает работать. Я полностью озадачен, любая помощь будет оценена.
Пояснение: тупик / код застревает внутри кода ALAssetsLibrary, а не внутри моего кода.
Дополнительная информация: у меня есть только один экземпляр ALAssetsLibrary, и я удостоверяюсь, что он не используется ни в каком другом потоке.
+(void)getDataFromAssetURL:(NSString *) myImageURL ofType:(enum ImageType)imageType andPerformBlock:(NSDataBlock)block blocking:(BOOL)blocking
{
NSConditionLock * albumReadLock = nil;
if (blocking) {
albumReadLock = [[NSConditionLock alloc] initWithCondition:PENDING];
}
@autoreleasepool {
@try {
NSURL *str = [[NSURL alloc] initWithString: myImageURL];
ALAsset * asset = [[AppManager sharedInstance].assetObjectCache objectForKey:str];
if (asset && NO) {
block( [Util getDataFromAsset:asset ofType:imageType] );
// notifies the lock that "all tasks are finished"
[albumReadLock lock];
[albumReadLock unlockWithCondition:ALLFINISHED];
}
else {
ALAssetsLibraryAssetForURLResultBlock resultblock = ^(ALAsset *myasset)
{
@autoreleasepool {
@try {
[[AppManager sharedInstance].assetObjectCache setObject:myasset forKey:str];
NSData * assetData = [Util getDataFromAsset:myasset ofType:imageType];
block(assetData);
// notifies the lock that "all tasks are finished"
[albumReadLock lock];
[albumReadLock unlockWithCondition:ALLFINISHED];
}
@catch (NSException *exception) {
block(nil);
// important: notifies lock that "all tasks finished" (even though they failed)
[albumReadLock lock];
[albumReadLock unlockWithCondition:ALLFINISHED];
}
@finally {
}
}
};
ALAssetsLibraryAccessFailureBlock failureblock = ^(NSError *myerror)
{
block(nil);
// important: notifies lock that "all tasks finished" (even though they failed)
[albumReadLock lock];
[albumReadLock unlockWithCondition:ALLFINISHED];
};
if(str)
{
NSURL *asseturl = str;
[[AppManager sharedInstance].assetslibrary assetForURL:asseturl
resultBlock:resultblock
failureBlock:failureblock];
}
else {
block(nil);
// notifies the lock that "all tasks are finished"
[albumReadLock lock];
[albumReadLock unlockWithCondition:ALLFINISHED];
}
}
}
@catch (NSException *exception) {
block(nil);
// notifies the lock that "all tasks are finished"
[albumReadLock lock];
[albumReadLock unlockWithCondition:ALLFINISHED];
}
@finally {
}
}
if (blocking) {
// non-busy wait for the asset read to finish (specifically until the condition is "all finished")
[albumReadLock lockWhenCondition:ALLFINISHED];
[albumReadLock unlock];
}
}
+(NSData *)getDataFromAsset:(ALAsset *)myasset ofType:(enum ImageType)imageType
{
ALAssetRepresentation *rep = [myasset defaultRepresentation];
CGImageRef iref = nil;
NSData *assetData = nil;
if (imageType == FULL_RESOLUTION) {
Byte *buffer = (Byte*)malloc(rep.size);
NSUInteger buffered = [rep getBytes:buffer fromOffset:0.0 length:rep.size error:nil];
assetData = [NSData dataWithBytesNoCopy:buffer length:buffered freeWhenDone:YES];
}
else if (imageType == LARGE_IMAGE){
iref = [rep fullScreenImage];
UIImage * uiimage = [UIImage imageWithCGImage:iref];
////NSLog(@"%f %f", uiimage.size.width, uiimage.size.height);
assetData = UIImageJPEGRepresentation(uiimage, 1.0f);
}
else if (imageType == SQUARE_THUMB){
iref = [myasset thumbnail];
assetData = UIImageJPEGRepresentation([UIImage imageWithCGImage:iref], 1.0f);
}
else if (imageType == PERSPECTIVE_THUMB){
iref = [myasset aspectRatioThumbnail];
assetData = UIImageJPEGRepresentation([UIImage imageWithCGImage:iref], 1.0f);
}
return assetData;
}
Новая информация: Оказывается, проблема возникает только на определенном устройстве. Как указано выше, если я приостанавливаю и снимаю паузу с отладчика в XCode, код движется вперед.
1 ответ
Вы вызовете взаимоблокировку в коде ALAsset, если инициируете этот блок кода из основного потока. Сначала вы должны перейти в фоновый поток, поскольку ALAssetsLibrary требует возможности выполнения кода в основном потоке, и если основной поток заблокирован так, как указано выше, то он будет ждать этого вечно.