【发布时间】:2013-05-15 20:14:20
【问题描述】:
我已经编写了两种方法来异步加载我的 UITableView 单元格中的图片。在这两种情况下,图像都可以正常加载,但是当我滚动表格时,图像会更改几次,直到滚动结束并且图像将返回到正确的图像。我不知道为什么会这样。
#define kBgQueue dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)
- (void)viewDidLoad
{
[super viewDidLoad];
dispatch_async(kBgQueue, ^{
NSData* data = [NSData dataWithContentsOfURL: [NSURL URLWithString:
@"http://myurl.com/getMovies.php"]];
[self performSelectorOnMainThread:@selector(fetchedData:)
withObject:data waitUntilDone:YES];
});
}
-(void)fetchedData:(NSData *)data
{
NSError* error;
myJson = [NSJSONSerialization
JSONObjectWithData:data
options:kNilOptions
error:&error];
[_myTableView reloadData];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
// Return the number of sections.
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
// Return the number of rows in the section.
// Usually the number of items in your array (the one that holds your list)
NSLog(@"myJson count: %d",[myJson count]);
return [myJson count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
myCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cell"];
if (cell == nil) {
cell = [[myCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"cell"];
}
dispatch_async(kBgQueue, ^{
NSData *imgData = [NSData dataWithContentsOfURL:[NSURL URLWithString:[NSString stringWithFormat:@"http://myurl.com/%@.jpg",[[myJson objectAtIndex:indexPath.row] objectForKey:@"movieId"]]]];
dispatch_async(dispatch_get_main_queue(), ^{
cell.poster.image = [UIImage imageWithData:imgData];
});
});
return cell;
}
... ...
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
myCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cell"];
if (cell == nil) {
cell = [[myCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"cell"];
}
NSURL* url = [NSURL URLWithString:[NSString stringWithFormat:@"http://myurl.com/%@.jpg",[[myJson objectAtIndex:indexPath.row] objectForKey:@"movieId"]]];
NSURLRequest* request = [NSURLRequest requestWithURL:url];
[NSURLConnection sendAsynchronousRequest:request
queue:[NSOperationQueue mainQueue]
completionHandler:^(NSURLResponse * response,
NSData * data,
NSError * error) {
if (!error){
cell.poster.image = [UIImage imageWithData:data];
// do whatever you want with image
}
}];
return cell;
}
【问题讨论】:
-
您正在尝试将信息存储在实际单元格中。这很糟糕,非常糟糕。您应该将信息存储在 n 数组(或类似的东西)中,然后将其显示在单元格中。本例中的信息是实际的 UIImage。是的,异步加载它,但将它加载到一个数组中。
-
@Fogmeister 你指的是
poster吗?这大概是他的自定义单元格中的一个图像视图,所以 EXEC_BAD_ACCESS 正在做的事情是完全正确的。您不应该将单元格用作模型数据的存储库是正确的,但我认为这不是他正在做的事情。他只是为自定义单元格提供了它需要展示自己的东西。此外,这是一个更微妙的问题,我会警惕将图像本身存储在支持 tableview 的模型数组中。最好使用图像缓存机制,并且您的模型对象应该从该缓存中检索。 -
是的,正是我的观点。查看请求(已完整显示),他正在异步下载图像并将其直接放入单元格中的 imageView 中。 (因此使用单元格来存储数据,即图像)。他应该做的是引用一个对象并从该对象请求图像(包含在数组或某处)。如果对象还没有图像,它应该返回一个占位符并下载图像。然后,当图像下载并准备好显示时,让表格知道,以便它可以更新单元格(如果它是可见的)。
-
每次他滚动到表格中的那个单元格时,他所做的都会强制下载。图像是否持久存储取决于他,但至少要在 tableview 的生命周期内存储它们。
-
正是 :D 这样您只需要从 URL 中获取图像一次。你会在 Facebook Friend Picker 之类的东西上看到这一点。当您启动它时,所有头像都是灰色的占位符。然后当你滚动它们时,它们都会随着它的移动而填充。但是,当您滚动回之前显示的单元格时,它会立即显示已下载的图像。
标签: ios objective-c cocoa-touch uitableview