Iphone 为什么不';是否在滚动之前加载UItableViewCell图像?
我的代码使用Iphone 为什么不';是否在滚动之前加载UItableViewCell图像?,iphone,objective-c,uitableview,nsurlconnection,Iphone,Objective C,Uitableview,Nsurlconnection,我的代码使用tableview:cellforrowatinexpath:方法异步下载图像,方法是使用initWithURL初始化IntentImage并调用downloadImage。此代码在向下滚动到UITableView中的新单元格UITableViewCell后运行良好,但不是在之前,即使URL在这两种情况下都是正确的。InternetImage的NSURLConnection委托方法都不会被调用来通知我连接的成功或失败,因为它们应该是这样的。调用reloadData:、setNeeds
tableview:cellforrowatinexpath:
方法异步下载图像,方法是使用initWithURL初始化IntentImage并调用downloadImage。此代码在向下滚动到UITableView中的新单元格UITableViewCell后运行良好,但不是在之前,即使URL在这两种情况下都是正确的。InternetImage的NSURLConnection委托方法都不会被调用来通知我连接的成功或失败,因为它们应该是这样的。调用reloadData:
、setNeedsDisplay:
、和setNeedsLayout:
时,由于映像无法下载,因此不执行任何操作
-(void) internetImageReady:(InternetImage*)downloadedImage
{
// The image has been downloaded. Put the image into the UIImageView
[imageView setImage:downloadedImage.Image];
}
以下是我的UiTableViewController子类中的代码:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
Object *object = (Object *)[self.array objectAtIndex:indexPath.row];
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cell"];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:@"cell"] autorelease];
}
cell.textLabel.text = object.attribute;
if (object.image == nil && object != nil) {
NSString *URLString = [[MyAppDelegate imageURLFromLink:(object.link) withExtension:@".jpg"]absoluteString];
InternetImage *asynchImage = [[InternetImage alloc] initWithUrl:URLString object:object];
[asynchImage downloadImage:self];
}
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
if (object.image != nil && object.thumbnailImage == nil) {
UIImage *image= (UIImage *) object.image;
UIImage *thumbnail = [image _imageScaledToSize:CGSizeMake(75.0, 50.0) interpolationQuality:20];
object.thumbnailImage = thumbnail;
}
cell.imageView.image = object.thumbnailImage;
return cell;
}
如果您询问为什么加载表后图像不会在后台下载,这是因为
tableView:cellforrowatinexpath:
仅在屏幕单元格的indexpath
中调用
如果您希望一次下载所有图像,而不是在屏幕上滚动单元格时下载,请编写一个方法,在array
属性中循环,并在其中初始化InternetImage
对象。这可能位于viewDidLoad
中
然后在UITableView委托中实现
tableView:willDisplayCell:forrowatinexpath:
,并让它负责将正确的InternetImage
对象分配给每个单元格的imageView
属性。我实际上花了一些时间查看代码
在InternetImage
中,我注意到有这个函数。
您需要做的是让此函数通知您的TableView
进行“刷新”。您可以通过向稍后调用的类传递委托函数来实现这一点,但现在事情变得非常棘手。因为当您离开视图时,您需要为您尝试下载的每个图像将委托函数设置为“nil”
-(void) internetImageReady:(InternetImage*)downloadedImage
{
// The image has been downloaded. Put the image into the UIImageView
[imageView setImage:downloadedImage.Image];
}
当你得到答案后,一定要把答案贴在这里,我很想看看这是否解决了问题。好的,很好的方法?
首先要检查您在哪里分配imageview?
第二,如果你的图像是固定的,这意味着特定于整个代码
if(cell == nil)
{
}
在那种情况下。我面临着同样的问题,并像这样解决了。
让我知道这是否有效。一个对我有效的解决方案是将下载的责任转移到对象,并将处理图像刷新的责任转移到表格单元格本身。如果对象在屏幕上可见并且具有相应的表格单元格,则图像下载后将立即刷新 该方法需要进行以下更改:
- 推卸责任 将图像下载到对象
- 修改对象以发送事件/调用委托/在图像更改时通知属性已更改
- 子类UITableViewCell以了解将显示的对象,该对象在被指定时将自身添加为对象的更改委托
// in the UITableViewController
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
Object *object = (Object *)[self.array objectAtIndex:indexPath.row];
ObjectTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"objectcell"];
if (nil == cell) {
cell = [[[ObjectTableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:@"objectcell"] autorelease];
}
cell.object = object;
return cell;
}
// in Object
- (void) downloadImageIfNeeded {
if (nil == image && nil == internetImage) {
NSString *URLString = [[MyAppDelegate imageURLFromLink:(object.link) withExtension:@".jpg"]absoluteString];
internetImage = [[InternetImage alloc] initWithUrl:URLString object:object];
[internetImage downloadImage:self];
}
}
- (void) internetImageReady:(InternetImage*)downloadedImage {
self.image = downloadedImage.image;
self.thumbnailImage = [image _imageScaledToSize:CGSizeMake(75.0, 50.0) interpolationQuality:20];
// notify the delegate
[imageDelegate imageChanged: self];
}
// in ObjectTableViewCell.h
@property (nonatomic, retain) Object *object;
// in ObjectTableViewCell.m
- (Object *) object {
return object;
}
- (void) setObject: (Object *) obj {
if (obj != object) {
object.imageDelegate = nil;
[object release];
object = nil;
if (nil != object) {
object = [obj retain];
object.imageDelegate = self;
[object downloadImageIfNeeded];
self.textLabel.text = object.attribute;
self.imageView.image = object.thumbnailImage;
self.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
}
}
- (void) imageChanged: (Object *) o {
self.imageView.image = object.thumbnailImage;
}
确实,只要表在滚动,NSUrlConnections就不会检索数据。一旦滚动停止,它会立即继续检索数据。然而,这种行为在任何iPhone应用程序中都可以看到(只要表格滚动,图像就不会加载),最后,我决定在我的应用程序中也使用这种行为。我想,苹果是故意这么做的。如果用户滚动速度非常快,可能是为了防止设备用大量图像请求冲击服务器;或者甚至可以随时为用户保持平滑滚动
不过,如果它至少能在缓慢滚动时工作,并且在快速滚动时仅阻止下载,那就太好了。好的,首先,您在这里发布的内容不是您正在使用的内容,或者您已经对您未提及的InternetImage进行了修改,因为InternetImage不响应initWithUrl:object:。您还没有将代码包含到委托方法internetImageReady:。我知道它不会在出现问题时被调用,但是一旦你开始滚动它就会被调用,对比正确情况下发生的情况将有助于人们诊断你的问题 此外,从您的描述中还不完全清楚滚动时会发生什么。很明显,后续的呼叫是有效的,但是之前尝试的所有连接是突然在该点启动,还是完全丢失 至于发生了什么,出于上述原因,我认为除了给你一些猜测之外,没有人能做得更多。如果我不得不打赌,我猜如果我在最后一段中所说的发生了,那么你的问题是(无论出于何种原因)主线程runloop不会处理NSURLConnections事件,直到有什么东西启动泵。这可能有很多原因,例如runloop处于错误的模式。您可以尝试手动运行NSRunLoop,或更改为InternetImage以显式设置runloop,或手动启动下载
-(void) internetImageReady:(InternetImage*)downloadedImage
{
// The image has been downloaded. Put the image into the UIImageView
[imageView setImage:downloadedImage.Image];
}
两个快速旁白
我没有答案,但我可以告诉你,我看到了同样的问题 我使用的是马克·约翰逊课程的一个稍加修改的版本。对图像的异步请求不会导致调用任何委托,直到我滚动tableview。当我将一个单元格从视图中滚动出来并返回时,调用会再次启动并正确获取数据 我在别处读到,NSURLConnection取决于运行循环是否处于某个特定的状态