Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/objective-c/23.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 使用dispatch\u async控制UICollectionView单元的负载顺序_Ios_Objective C_Asynchronous_Uicollectionview - Fatal编程技术网

Ios 使用dispatch\u async控制UICollectionView单元的负载顺序

Ios 使用dispatch\u async控制UICollectionView单元的负载顺序,ios,objective-c,asynchronous,uicollectionview,Ios,Objective C,Asynchronous,Uicollectionview,在我的iOS应用程序中,我有一个UICollectionView,其中每个单元格都包含一个图像。为了避免加载视图花费很长时间,在后台任务中加载图像内容之前,我先加载每个视图,其中包含一个空白图像和标题 我记录了在后台异步任务中加载的图像,看起来屏幕外的单元格图像首先加载,然后是屏幕顶部的单元格。这使得应用程序看起来没有响应,我宁愿让最上面的单元格优先加载: 我还注意到,一旦我开始滚动,单元格中的图像就会突然出现,但它们自己出现的时间要长得多有人能提出控制UICollectionCells加载顺

在我的iOS应用程序中,我有一个UICollectionView,其中每个单元格都包含一个图像。为了避免加载视图花费很长时间,在后台任务中加载图像内容之前,我先加载每个视图,其中包含一个空白图像和标题

我记录了在后台异步任务中加载的图像,看起来屏幕外的单元格图像首先加载,然后是屏幕顶部的单元格。这使得应用程序看起来没有响应,我宁愿让最上面的单元格优先加载:

我还注意到,一旦我开始滚动,单元格中的图像就会突然出现,但它们自己出现的时间要长得多有人能提出控制UICollectionCells加载顺序的策略吗?

这是我的密码:

迭代项目并将ImageView添加到NSMutableArray projectContainers,然后将其转换为单元格

for (NSDictionary *currentProject in projects)
    {
        // data entry
        [projectIDs addObject: [currentProject objectForKey:@"id"]];
        NSString *projectTitle = [currentProject objectForKey:@"title"];

        id delegate = [[UIApplication sharedApplication] delegate];
        self.managedObjectContext = [delegate managedObjectContext];

        CustomLabel *cellLabel=[[CustomLabel alloc]init];
        cellLabel.text = trimmedProjectTitle;
        [titles addObject:projectTitle];

        CGSize maxLabelSize = CGSizeMake(cellWidth,100);

        CustomLabel *titleLabel = [[CustomLabel alloc]init]; 
        // titleLabel styling
        titleLabel.backgroundColor = [[UIColor blackColor]colorWithAlphaComponent:0.5f];
        titleLabel.textColor =[UIColor whiteColor];
        [titleLabel setFont: [UIFont fontWithName: @"HelveticaNeue" size:12]];

        titleLabel.text = trimmedProjectTitle;
        CGSize expectedLabelSize = [titleLabel.text sizeWithFont:titleLabel.font constrainedToSize:maxLabelSize lineBreakMode:NSLineBreakByWordWrapping];

        CGRect labelFrame = (CGRectMake(0, 0, cellWidth, 0));
        labelFrame.origin.x = 0;
        labelFrame.origin.y = screenWidth/2 - 80 - expectedLabelSize.height;
        labelFrame.size.height = expectedLabelSize.height+10;
        titleLabel.frame = labelFrame;

        // add placeholder image with textlabel
        UIImageView *imagePreview = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, cellWidth, cellHeight)];
        imagePreview.contentMode= UIViewContentModeScaleAspectFill;
        imagePreview.clipsToBounds = YES;
        [imagePreview setImage:[UIImage imageNamed:@"blank.png"]];
        [imagePreview addSubview:titleLabel];
        [imagePreview.subviews[0] setClipsToBounds:YES];
        [projectContainers addObject: imagePreview];

        // add project thumbnail images in async
        dispatch_async(bgQueue, ^{
          NSDictionary *imagePath = [currentProject objectForKey:@"image_path"];
          NSString *imageUrlString = [imagePath objectForKey: @"preview"];
          NSURL *imageUrl = [NSURL URLWithString: imageUrlString];
          NSData *imageData = [[NSData alloc] initWithContentsOfURL:(imageUrl)];
          UIImage *image = [[UIImage alloc] initWithData:(imageData)];
          if(image){
              NSLog(@"project with image: %@", projectTitle);
              [imagePreview setImage: image];
          }
            BOOL *builtVal = [[currentProject objectForKey:@"built"]boolValue];
            if(builtVal){
                UIImageView *builtBanner =[[UIImageView alloc]initWithImage:[UIImage imageNamed:@"built_icon.png"]];
                builtBanner.frame = CGRectMake(screenWidth/2 -80, 0, 50, 50);
                [imagePreview addSubview: builtBanner];
            }
        });
    }
使用NSMutableArray项目容器渲染单元格:

-(UICollectionViewCell*)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
//    NSLog(@"cellForItemAtIndexPath");
        static NSString *identifier = @"NewCell";
        UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:identifier forIndexPath:indexPath];
        if(!reloadProjects){
            UIImageView *preview = (UIImageView*) [cell.contentView viewWithTag:[[projectIDs objectAtIndex:indexPath.row]intValue]];
            UIImageView *previewContent = [projectContainers objectAtIndex:indexPath.row];
            //    NSLog(@"fetching image tag %d", [[projectIDs objectAtIndex:indexPath.row]intValue]);

            if (!preview)
            {
                previewContent.tag = [[projectIDs objectAtIndex:indexPath.row]intValue];
                //        NSLog(@"creating previewContent %li", (long) previewContent.tag);
                [cell addSubview: previewContent];
            }

            [self.collectionView setBackgroundColor:collectionGrey];
            cell.contentView.layer.backgroundColor  = [UIColor whiteColor].CGColor;

            return cell;
        }
    return cell;
}
编辑:工作解决方案

感谢rob mayoff帮我想出了一个解决方案。这就是我最后所做的,它可以更快地加载图像:

// add project thumbnail images in async
        dispatch_async(imageQueue, ^{
          NSDictionary *imagePath = [currentProject objectForKey:@"image_path"];
          NSString *imageUrlString = [imagePath objectForKey: @"preview"];
          NSURL *imageUrl = [NSURL URLWithString: imageUrlString];
          NSData *imageData = [[NSData alloc] initWithContentsOfURL:(imageUrl)];
          UIImage *image = [[UIImage alloc] initWithData:(imageData)];
          if(image){
              dispatch_async(dispatch_get_main_queue(), ^{
                    NSLog(@"project with image: %@", projectTitle);
                    [imagePreview setImage: image];
              });
          }
            BOOL *builtVal = [[currentProject objectForKey:@"built"]boolValue];
            if(builtVal){
                UIImageView *builtBanner =[[UIImageView alloc]initWithImage:[UIImage imageNamed:@"built_icon.png"]];
                builtBanner.frame = CGRectMake(screenWidth/2 -80, 0, 50, 50);
                dispatch_async(dispatch_get_main_queue(), ^{
                    [imagePreview addSubview: builtBanner];
                });
            }
        });

在你的代码中有几点需要改进,但你的主要抱怨(“一旦我开始滚动,单元格中的图像突然开始出现,但它们自己出现的时间要长得多”)是因为你违反了命令:

你只能进入 您的视图层次结构 从主线程开始。 看看你的代码:

    dispatch_async(bgQueue, ^{
        ...
            [imagePreview addSubview: builtBanner];
您正在从后台线程操作视图层次结构。这是不允许的。例如,请参见的底部注释或

您需要调度回主线程以更新视图层次结构


看电视。它深入地讨论了如何高效地完成你想做的事情。另请参见。

感谢您的帮助,并为我指明了正确的方向。我会研究你的建议,看看我是否能解决我的问题!