NSURLConnection 在 UITableView 滚动之前不会“触发”
Posted
技术标签:
【中文标题】NSURLConnection 在 UITableView 滚动之前不会“触发”【英文标题】:NSURLConnection not "firing" until UITableView scrolls 【发布时间】:2010-06-09 06:19:59 【问题描述】:我有一个 UITableView,它异步加载图像并在加载后将其放置在 UITableViewCell 中(我使用的代码与“LazyTableImages”教程中的代码几乎完全相同)。当我滚动表格时,这适用于所有图像,但它不会加载视图中的第一个图像。
代码确实可以正常工作,因为正确调用了实际发送 NSURLConnection 请求的类(我添加了一个 NSLog 并到达了控制台)。 NSURLConnection 只是不调用委托方法(didReceiveData、connectionDidFinishLoading 等)。
这是我的代码:
HomeController.m
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
static NSString *CellIdentifier = @"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
NSArray *feed = [feeds objectAtIndex: indexPath.row];
/**
* Name of person
*/
[...]
/**
* Feed entry
*/
[...]
/**
* Misc work
*/
[...]
FeedRecord *feedRecord = [self.entries objectAtIndex:indexPath.row];
if( !feedRecord.image )
if (self.table.dragging == NO && self.table.decelerating == NO)
[self startIconDownload:feedRecord forIndexPath:indexPath];
cell.imageView.image = [UIImage imageNamed:@"Placeholder.png"];
return cell;
- (void)startIconDownload:(FeedRecord *)feedRecord forIndexPath:(NSIndexPath *)indexPath
IconDownloader *iconDownloader = [imageDownloadsInProgress objectForKey:indexPath];
if (iconDownloader == nil)
iconDownloader = [[IconDownloader alloc] init];
iconDownloader.feedRecord = feedRecord;
iconDownloader.indexPathInTableView = indexPath;
iconDownloader.delegate = self;
[imageDownloadsInProgress setObject:iconDownloader forKey:indexPath];
[iconDownloader startDownload];
[iconDownloader release];
IconDownload.m
#import "IconDownloader.h"
#import "FeedRecord.h"
#define kAppIconHeight 48
@implementation IconDownloader
@synthesize feedRecord;
@synthesize indexPathInTableView;
@synthesize delegate;
@synthesize activeDownload;
@synthesize imageConnection;
#pragma mark
- (void)dealloc
[feedRecord release];
[indexPathInTableView release];
[activeDownload release];
[imageConnection cancel];
[imageConnection release];
[super dealloc];
- (void)startDownload
NSLog(@"%@ %@",@"Started downloading", feedRecord.profilePicture); // this shows in log
self.activeDownload = [NSMutableData data];
// alloc+init and start an NSURLConnection; release on completion/failure
NSURLConnection *conn = [[NSURLConnection alloc] initWithRequest:
[NSURLRequest requestWithURL:
[NSURL URLWithString:feedRecord.profilePicture]] delegate:self];
self.imageConnection = conn;
NSLog(@"%@",conn); // this shows in log
[conn release];
- (void)cancelDownload
[self.imageConnection cancel];
self.imageConnection = nil;
self.activeDownload = nil;
#pragma mark -
#pragma mark Download support (NSURLConnectionDelegate)
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
NSLog(@"%@ %@",@"Got data for", feedRecord.profilePicture);
[self.activeDownload appendData:data];
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
NSLog(@"%@",@"Fail!");
// Clear the activeDownload property to allow later attempts
self.activeDownload = nil;
// Release the connection now that it's finished
self.imageConnection = nil;
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
NSLog(@"%@ %@",@"Done", feedRecord.profilePicture);
// Set appIcon and clear temporary data/image
UIImage *image = [[UIImage alloc] initWithData:self.activeDownload];
self.feedRecord.image = image;
self.activeDownload = nil;
[image release];
// Release the connection now that it's finished
self.imageConnection = nil;
NSLog(@"%@ %@",@"Our delegate is",delegate);
// call our delegate and tell it that our icon is ready for display
[delegate feedImageDidLoad:self.indexPathInTableView];
@end
是否有其他人遇到过类似的情况或可以识别我的代码存在问题?谢谢!
【问题讨论】:
【参考方案1】:您可以使用此代码
[tableView performSelector:@selector(reloadData) onThread:[NSThread mainThread] withObject:nil waitUntilDone:YES];
改为
[tableView reloadData];
【讨论】:
【参考方案2】:您不会调用您在 startDownload 方法中创建的 NSURLConnection 对象的 start 方法。
一定要这样做:
- (void)startDownload
NSLog(@"%@ %@",@"Started downloading", feedRecord.profilePicture); // this shows in log
self.activeDownload = [NSMutableData data];
// alloc+init and start an NSURLConnection; release on completion/failure
NSURLConnection *conn = [[NSURLConnection alloc] initWithRequest:
[NSURLRequest requestWithURL:
[NSURL URLWithString:feedRecord.profilePicture]] delegate:self];
self.imageConnection = conn;
NSLog(@"%@",conn); // this shows in log
[conn start];
[conn release];
你也可以使用构造函数:initWithRequest:delegate:startImmediately:
此外,如果用户滚动,您的下载将被阻止,因为它们正在运行的运行循环。只需在“常用模式”中注册您的连接:
[conn scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes];
摘自:how-to-avoid-blocked-downloads-during-scrolling
【讨论】:
【参考方案3】:您没有启动我们的NSURLConnection
。要么用-[NSURLConnection initWithRequest:delegate:startImmediately:]
初始化它,要么在初始化后手动调用-[NSURLConnection start]
。
【讨论】:
不。我得到的代码将初始化请求并立即开始下载 URL。 (Apple 的方法文档:“返回一个初始化的 URL 连接并开始加载 URL 请求的数据。”)。 [NSURLConnection start] 也不起作用:( 很抱歉我误读了文档。实际上,我看不到您的代码有问题。是否在 startDownload 方法中设置了断点并检查是否一切都如预期的那样?【参考方案4】:我也有同样的问题。此外,我几乎使用与您相同的代码(来自 Apple 示例 LazyTableImages)。
虽然 Apple 的测试项目中的代码有效,但它在我的项目中不起作用 - 尽管我只是复制了 Apple 的代码。
我发现的是:我用的时候
NSLog(@"Is%@ main thread", ([NSThread isMainThread] ? @"" : @" NOT"));
在 cellForRowAtIndexPath: 以及 IconDownload.m 的 startDownload: 中(在两个项目中),我发现它是 Apple 示例中的主线程,但在我的代码中 NOT 主线程。 p>
这可能是问题所在。
知道怎么解决吗?
编辑!!!解决了!
我只是强制使用主线程
NSDictionary *info = [NSDictionary dictionaryWithObjectsAndKeys:entry.imageURL, @"imageURL", indexPath, @"indexPath", nil];
[self performSelectorOnMainThread:@selector(startIconDownload:) withObject:info waitUntilDone:NO];
在 cellForRowAtIndexPath 中:您需要一个字典来向该方法发送多个参数。
您可以在代码中执行类似的解决方案。换行:
[self startIconDownload:feedRecord forIndexPath:indexPath];
用我的代码修改 startIconDownload: 像这样
- (void)startIconDownload:(NSDictionary *)info
NSString *url = [info objectForKey:@"imageURL"];
NSIndexPath *indexPath = [info objectForKey:@"indexPath"];
...
您的应用中的某些变量可能会有所不同。
但我只是不明白为什么它在不强制主线程的情况下在 Apple 的示例中工作。
有什么想法吗?
【讨论】:
【参考方案5】:看看这里:http://www.depl0y.com/?p=345 也许会有所帮助。
编辑:是的,正在为我工作。让我知道是否也适合您,或者您需要更多信息。
【讨论】:
以上是关于NSURLConnection 在 UITableView 滚动之前不会“触发”的主要内容,如果未能解决你的问题,请参考以下文章
如何将文本包装在 Iphone 的 UITable 单元格中?