0

在我的应用程序中,当用户按下 中的其中一个选项卡UITabBar时,加载视图并将其显示给用户需要花费太多时间,因此可能会造成混淆(这是因为我在 中从网络加载图像UITableView)。所以,我决定在所有图像完成加载之前使用多线程来显示视图。

我正在使用这段代码:

- (UITableViewCell *)tableView:(UITableView *)tableView
           cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    static NSString *CellIdentifier = @"Cell";
    cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [[SetsCustomCell alloc] initWithFrame:CGRectZero];
    }
    // getting url
    NSURL* imgUrl = [[NSURL alloc]initWithString:[[mainArray objectAtIndex:
                       indexPath.row]valueForKey:@"imageURL"]];
    //put this url and current cell in the dictionary
    NSDictionary* params = [NSDictionary dictionaryWithObjectsAndKeys:
                    imgUrl,@"localUrl",cell,@"localCell", nil];
   // multithreading time (calling loadImageWithParams method)
    [self performSelectorInBackground:@selector(loadImageWithParams:)
                           withObject:params];
    return cell;
}
-(void)loadImageWithParams:(NSDictionary*)params {
    NSURL* url = [params objectForKey:@"localUrl"];
    cell = [params objectForKey:@"localCell"];
    UIImage* thumb = [UIImage imageWithData:[NSData dataWithContentsOfURL:url]];
    NSDictionary* backParams = [NSDictionary dictionaryWithObjectsAndKeys: 
                   cell,@"localCell",thumb,@"thumb", nil];
    [self performSelectorOnMainThread:@selector(setImage:)
                        withObject:backParams waitUntilDone:YES];
}
-(void)setImage:(NSDictionary*)params{
    cell = [params objectForKey:@"localCell"];
    UIImage* thumb = [params objectForKey:@"thumb"];
    [cell.imageView setImage:thumb];
    cell.imageView.hidden = NO;
    [cell setNeedsLayout];
}

我只有两个单元格,UITableView问题是只有第二个单元格加载它的图像。第一个单元格仍然是空的。但是,如果我滚动UITableView直到第一个单元格不再可见,然后cellForRowAtIndexPath:再次调用,第一个单元格将获取其图像。

我也尝试过使用多线程,NSOperationQueueGCD结果相同。

似乎我不清楚多线程是如何工作的,但如果有人指出我的错误,我将非常感激。

谢谢!

4

4 回答 4

2

我过去这样做的方法是创建一个 NSObject 子类来存储图像。然后 UITableView 的数据存储是这些对象的数组,而不是 URL 路径。

然后你可以像这样延迟加载图像......

对象模型.h

@property (nonatomic, strong) UIImage *image;

对象模型.m

- (UIImage*)image
{
    if (_image == nil) {
        [self downloadImage];
        return [UIImage imageNamed:@"placeholderImage"];
    }
    return _image;
}

- (void)downloadImage
{
    //Put your async stuff here to download the image then reload the tableView when it's done.
}

通过这样做,您将图像存储在数据存储中,同时也在其自己的类中管理下载内容并保持 TVC 清洁。

于 2013-02-02T18:21:49.287 回答
1

看起来你把这个复杂化了——我真的不明白你在用 params 字典做什么。为什么不显示控制器,然后在 viewDidAppear 中开始下载。当结果回来时,用它们填充你的数组,然后调用 reloadData。除了可以立即加载的图像之外,这些单元格中是否还有其他内容?

于 2013-02-02T18:24:56.847 回答
1

典型的做法是实现一个在后台下载/加载图像的 LazyUIImage 类。在下载图像时,显示类似于 UIActivityIndi​​cator 的内容。当图像到达 LazyUIImage 时,发出通知并停止活动指示符(并可能将其从视图中删除)。对于每个包含 LazyUIImage 的视图控制器,处理该通知,例如,执行 [myTable reloadData]。在 LazyUIImage 中,编写一个名为 getImage 的方法,该方法在加载图像时返回 nil,并在加载图像后返回图像。

编辑:实际上,如果您将 LazyUIImage 实现为 LazyUIImageView 那么您不需要在包含视图控制器中重新加载任何内容:在 LazyUIImageView 中放置一个顶级背景视图,然后切换出实际 UIImageView 的 UIActivityIndi​​cator 子视图图片下载完成。

于 2013-02-02T18:49:22.140 回答
-2

你需要做延迟加载的东西。使用 NSOperationQueue 搜索延迟加载。

于 2013-02-02T18:30:03.537 回答