Код застрял при запросе свойства размера 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 требует возможности выполнения кода в основном потоке, и если основной поток заблокирован так, как указано выше, то он будет ждать этого вечно.

Другие вопросы по тегам