【问题标题】:Load image to UICollectionView Asynchronously?将图像异步加载到 UICollectionView?
【发布时间】:2013-08-03 08:38:33
【问题描述】:

如何将图像异步加载到UICollectionview? 在下面的方法里面?

- (PSTCollectionViewCell *)collectionView:(PSTCollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {

 bookImage = [UIImage imageWithContentsOfFile:[NSString stringWithFormat:@"%@/%@", docPath, [[preview objectAtIndex:indexPath.row] lastPathComponent]]];
 [[cell grid_image] setImage:bookImage];

}

viewdidload() 中,我使用以下异步调用将图像加载到“预览”NSMutablearray

 dispatch_queue_t imageLoadQueue = dispatch_queue_create("com.GMM.assamkar", NULL);

dispatch_async(imageLoadQueue, ^{
    //Wait for 5 seconds...
    usleep(1000000);
    docPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];


    for(int k=0; k <[allImage count] ;k++){


        imgURL = [allImage objectAtIndex:k];
        [imagePreview addObject:imgURL];
        imgData=[NSData dataWithContentsOfURL:[NSURL URLWithString:imgURL]];


        [imgData writeToFile:[NSString stringWithFormat:@"%@/%@", docPath, [allImage lastPathComponent]] atomically:YES];

    }

    [[self collectionView] reloadData];


});

请帮帮我..现在加载时间太长了...

【问题讨论】:

  • 具体是什么时间太长了?图片的尺寸是多少?
  • 你应该做这个 [[self collectionView] reloadData];在主线程中。这不是一个答案。这只是评论。
  • 使用 EGOImageView : github.com/enormego/EGOImageLoading

标签: ios objective-c asynchronous uicollectionview


【解决方案1】:

试图回答您的主要问题“如何将图像异步加载到UICollectionview?”

我会建议“Natasha Murashevhere 提供的解决方案,它对我来说效果很好,而且很简单。

如果 imgURL = [allImage objectAtIndex:k];allImage 属性中保留 URL 数组,则像这样更新 collectionView:cellForItemAtIndexPath: 方法:

- (PSTCollectionViewCell *)collectionView:(PSTCollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
    NSURL *url = [NSURL URLWithString:[allImage objectAtIndex:indexPath]];

    [self downloadImageWithURL:url completionBlock:^(BOOL succeeded, NSData *data) {
        if (succeeded) {
            cell.grid_image.image = [[UIImage alloc] initWithData:data];
        }
    }];
}

然后将downloadImageWithURL:completionBlock: 方法添加到您的类中,该方法将异步加载图像并在成功下载图像后自动更新CollectionView 中的单元格。

- (void)downloadImageWithURL:(NSURL *)url completionBlock:(void (^)(BOOL succeeded, NSData *data))completionBlock
{
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
    [NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
        if (!error) {
            completionBlock(YES, data);
        } else {
            completionBlock(NO, nil);
        }
    }];
}

我看到您尝试在视图出现之前预加载图像,所以也许我的解决方案不是您想要的,但是从您的问题很难说。无论如何,你也可以通过它实现你想要的。

斯威夫特 2.2 Swift 中的解决方案。

public typealias ImageFetchCompletionClosure = (image: UIImage?, error: NSError?, imageURL: NSURL?) -> Void

extension String {
   func fetchImage(completionHandler: (image: UIImage?, error: NSError?, imageURL: NSURL?) -> Void) {
        if let imageURL = NSURL(string: self) {
            NSURLSession.sharedSession().dataTaskWithURL(imageURL) { data, response, error in
                guard
                    let httpURLResponse = response as? NSHTTPURLResponse where httpURLResponse.statusCode == 200,
                    let mimeType = response?.MIMEType where mimeType.hasPrefix("image"),
                    let data = data where error == nil,
                    let image = UIImage(data: data)
                    else {
                        if error != nil {
                            completionHandler(image: nil, error: error, imageURL: imageURL)
                        }
                        return
                }
                dispatch_sync(dispatch_get_main_queue()) { () -> Void in
                    completionHandler(image: image, error: nil, imageURL: imageURL)
                }
            }.resume()
        }
    }
}

使用示例:

    "url_string".fetchImage { (image, error, imageURL) in
        // handle different results, either image was downloaded or error received
    }

【讨论】:

  • 是不是像单元格可以重复使用,并且您可以用其他一些图像数据有效地覆盖单元格?您的示例中的单元格也未定义;)
  • 它主要是为了回答如何异步加载图像,而不是如何有效地使用单元格:) 不过,谢谢指出。
【解决方案2】:

此代码创建串行队列:

dispatch_queue_t imageLoadQueue = dispatch_queue_create("com.GMM.assamkar", NULL);

因此,IN QUEUE 中的每个任务都在同一个线程中连续执行。因此,每个加载任务都会通过睡眠来维持您的单个工作线程,这会减慢所有加载过程。

通过类似的方式使用异步 CONCURRENT 队列:

dispatch_queue_t imageLoadQueue = dispatch_queue_create("com.GMM.assamkar", DISPATCH_QUEUE_CONCURRENT);

【讨论】:

  • 所以并在主线程上使用 reloadData。就像那个 dispatch_async(dispatch_get_main_queue(), ^{ //reloadData });
  • 我想我应该使用一种新的延迟加载方法来显示我的 PSTCollectionView
【解决方案3】:

根据您的要求使用延迟加载文件。

LazyLoad.h
LazyLoad.m

像这样使用它们

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
    UICollectionViewCell *cell=[collectionView dequeueReusableCellWithReuseIdentifier:@"cellIdentifier" forIndexPath:indexPath];

    [cell addSubview:[self addViewWithURL:@"http://openwalls.com/image/399/explosion_of_colors_1920x1200.jpg" NFrame:CGRectMake(0, 0, 50, 50)]];

    cell.backgroundColor=[UIColor blueColor];
    return cell;
}

-(UIView*)addViewWithURL:(NSString*)urlStr NFrame:(CGRect)rect
{
    LazyLoad *lazyLoading;

    lazyLoading = [[LazyLoad alloc] init];
    [lazyLoading setBackgroundColor:[UIColor grayColor]];
    [lazyLoading setFrame:rect];

    [lazyLoading loadImageFromURL:[NSURL URLWithString:urlStr]];
    return lazyLoading;
}

Download Demo Here

【讨论】:

  • 如何在 UICollectionview cell.imageview.image 中显示图像,这是我的问题
  • cell.imageview.image 属性在 CollectionView 中不存在,仅在 tableView 中。MyCode 将异步加载图像并作为子视图添加到 collectionView 单元格中。
  • stackoverflow.com/a/17856406/1305001 添加 myCode 或者你需要使用自定义单元格
  • 您的代码不工作并且 /H 和 .M 文件的链接为空
  • Heloo,我需要在 cell.image 中显示我的自定义单元格图像视图,但您使用的是 uiview。
猜你喜欢
  • 1970-01-01
  • 2015-08-08
  • 2012-04-04
  • 2017-12-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多