Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/114.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios AlassetLibrary assetForURL方法的同步问题_Ios_Objective C_Synchronization_Alassetslibrary - Fatal编程技术网

Ios AlassetLibrary assetForURL方法的同步问题

Ios AlassetLibrary assetForURL方法的同步问题,ios,objective-c,synchronization,alassetslibrary,Ios,Objective C,Synchronization,Alassetslibrary,从ALAssetsLibrary加载资产时出现一些同步问题 事实上,我正在尝试的是从摄影机滚动加载一些图片,这些图片的URL由一些数据库查询提供。现在,从数据库获取URL后,我使用assetForURL方法加载图片,加载图片后,我将图片显示到某个视图。因此,我在每次查询结果集返回记录时执行的循环中调用该方法。直到现在一切都很顺利。下面是演示该过程的示例代码: ALAssetsLibrary* library = [ALAssetsLibrary new]; //dispatch_group_t

ALAssetsLibrary
加载资产时出现一些同步问题

事实上,我正在尝试的是从摄影机滚动加载一些图片,这些图片的URL由一些数据库查询提供。现在,从数据库获取URL后,我使用
assetForURL
方法加载图片,加载图片后,我将图片显示到某个视图。因此,我在每次查询结果集返回记录时执行的循环中调用该方法。直到现在一切都很顺利。下面是演示该过程的示例代码:

ALAssetsLibrary* library = [ALAssetsLibrary new];
//dispatch_group_t queueGroup = dispatch_group_create();
while ([rs next]) {
    //some data load up

    //load thumbnails of available images
    [library assetForURL:url resultBlock:^(ALAsset *asset) {
        UIImage* img = [[UIImage imageWithCGImage:asset.aspectRatioThumbnail] retain];

        //dispatch_group_async(queueGroup, dispatch_get_main_queue(), ^{
            //create views and add to container view
            CGFloat left = (8.0f + dimension) * i + 8.0f;
            CGRect rect = CGRectMake(left, 8.0f, dimension, dimension);
            TileView* tileView = [[NSBundle mainBundle] loadNibNamed:@"TileView" owner:nil options:nil][0];
            [tileView setFrame:rect];
            tileView.tag = i;
            tileView.active = NO;
            [self.thumbnailContainer addSubview:tileView];

                            //display image in tileView, etc.

                            //.............
            if (img) {
                [img release];
            }
            NSLog(@"block %d: %d",i,[self.thumbnailContainer.subviews count]);
            //});
    } failureBlock:^(NSError *error) {
        NSLog(@"failed to load image");
    }];

    i++;
}

NSLog(@"outside block %d",[self.thumbnailContainer.subviews count]);
[library release];
在我的代码中,thumbnailContainer是一个UIScrollView,在它里面我添加了自定义视图来显示缩略图图像,它可以正常工作

当我试图选择添加到
self.thumbnailContainer
中的最后一个视图时,真正的困境出现了。我找不到任何方法来确定
assetForURL
方法的所有异步块何时完成,以便
self.thumbnailContainer
实际上包含一些子视图。因此,如果我在循环完成后立即记录
self.thumbnailContainer
的子视图计数,它将显示0。在那之后,我发现所有的块代码都被执行,子视图的数量也在增加。这是很正常的行为,但与我的要求相矛盾。我尝试过GCD的
dispatch\u group\u
dispatch\u wait
方法,但没有成功


任何人都可以建议一种解决方法或替代编码模式来克服这种情况。任何帮助都将不胜感激。谢谢。

有两种方法可以解决此问题。是的

1.NSLock。特别是NSConditionLock。基本上,您创建了一个条件为“挂起的任务”的锁。然后在assetForURL的完成和错误块中,使用“全部完成”条件将其解锁。这样,在调用assetForURL之后,只需使用“all complete”标识符调用lockWhenCondition,就完成了(它将等待块设置该条件)

2.在
resultBlock
failureBlock

注意:


关于ALAsset库的性能,我已经提到了一些重要的事情。

有两种方法可以解决这个问题。是的

1.NSLock。特别是NSConditionLock。基本上,您创建了一个条件为“挂起的任务”的锁。然后在assetForURL的完成和错误块中,使用“全部完成”条件将其解锁。这样,在调用assetForURL之后,只需使用“all complete”标识符调用lockWhenCondition,就完成了(它将等待块设置该条件)

2.在
resultBlock
failureBlock

注意:


关于ALAsset库的性能,我已经提到了几件重要的事情。

您可以使用调度组,正如您可能想到的那样:

- (void) loadViewsWithCompletion:(completion_t)completionHandler {
    ALAssetsLibrary* library = [ALAssetsLibrary new];
    dispatch_group_t group = dispatch_group_create();
    while ([rs next]) {
        dispatch_group_enter(group);
        [library assetForURL:url resultBlock:^(ALAsset *asset) {
            UIImage* img = [[UIImage imageWithCGImage:asset.aspectRatioThumbnail] retain];

            dispatch_async(dispatch_get_main_queue(), ^{
                //create views and add to container view
                ...

                dispatch_group_leave(group);
            });
        } failureBlock:^(NSError *error) {
            NSLog(@"failed to load image");
            dispatch_group_leave(group);
        }];

        i++;
    }
    [library release];
    if (completionHandler) {
        dispatch_group_notify(group, ^{
            completionHandler(someResult);
        });
    }
    ...  release dispatch group if not ARC
}
但代码可能存在潜在问题:

由于异步加载图像,因此它们可能全部并行加载。这可能会消耗大量的系统资源。如果是这种情况,这取决于资产加载程序方法的实现
assetForURL:resultBlock:failureBlock:
,则需要序列化循环

注意:方法
assetForURL:resultBlock:failureBlock:
可能已经确保对资产库的访问被序列化。如果完成块的执行上下文也是串行队列,
[UIImage imageWithCGImage:asset.aspectRatioThumbnail]
将串行执行。在这种情况下,您的循环只是将多个任务排队,但一次只处理一个映像,这样您就安全了


否则,如果方法
assetForURL:resultBlock:failureBlock:
并行运行,和/或块执行并发队列,则可能并行加载和处理图像。如果这些图像很大,这可能是一件坏事。

您可能会利用调度组,正如您可能想到的:

- (void) loadViewsWithCompletion:(completion_t)completionHandler {
    ALAssetsLibrary* library = [ALAssetsLibrary new];
    dispatch_group_t group = dispatch_group_create();
    while ([rs next]) {
        dispatch_group_enter(group);
        [library assetForURL:url resultBlock:^(ALAsset *asset) {
            UIImage* img = [[UIImage imageWithCGImage:asset.aspectRatioThumbnail] retain];

            dispatch_async(dispatch_get_main_queue(), ^{
                //create views and add to container view
                ...

                dispatch_group_leave(group);
            });
        } failureBlock:^(NSError *error) {
            NSLog(@"failed to load image");
            dispatch_group_leave(group);
        }];

        i++;
    }
    [library release];
    if (completionHandler) {
        dispatch_group_notify(group, ^{
            completionHandler(someResult);
        });
    }
    ...  release dispatch group if not ARC
}
但代码可能存在潜在问题:

由于异步加载图像,因此它们可能全部并行加载。这可能会消耗大量的系统资源。如果是这种情况,这取决于资产加载程序方法的实现
assetForURL:resultBlock:failureBlock:
,则需要序列化循环

注意:方法
assetForURL:resultBlock:failureBlock:
可能已经确保对资产库的访问被序列化。如果完成块的执行上下文也是串行队列,
[UIImage imageWithCGImage:asset.aspectRatioThumbnail]
将串行执行。在这种情况下,您的循环只是将多个任务排队,但一次只处理一个映像,这样您就安全了


否则,如果方法
assetForURL:resultBlock:failureBlock:
并行运行,和/或块执行并发队列,则可能并行加载和处理图像。如果这些图像太大,这可能是一件坏事。

谢谢您的回复。但是,我同意您的回答中的一个命题,即
assetForURL
块在单独的线程上工作。在我自己的应用程序中,我发现这些块在主线程本身上工作,但是,这些块异步排队到主队列,也就是说,当成功加载资产时,
resultBlock
在主队列中排队。资产加载过程本身仍然在某些不同的线程上工作。我会尽力处理你的
NSConditionLock
建议,然后回来。再次感谢。不过,请使用dispatch_async(dispatch_get_main_queue())并在ui部分感受不同之处。感谢您的回复。不过,我还是同意一位专业人士的说法