2010-06-09 41 views
2

我有一个UITableView异步加载图像,并将其放置在UITableViewCell一旦它被加载(我使用几乎完全相同的代码,在“LazyTableImages”教程)。当我滚动表格时,这对所有图像都适用,但不会加载视图中第一个图像。NSURLConnection不是“射击”,直到UITableView滚动

代码肯定工作正常,因为实际发送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 

是否有其他人遇到类似这样的事情,或者可以识别我的代码问题?谢谢!

回答

0

你不会开始我们的NSURLConnection。可以使用-[NSURLConnection initWithRequest:delegate:startImmediately:]进行初始化,也可以在初始化后手动调用-[NSURLConnection start]

+0

都能跟得上。我得到的代码将初始化请求并立即开始下载URL。 (该方法的Apple文档:“返回初始化的URL连接并开始加载URL请求的数据。”)。 [NSURLConnection start]也不起作用:( – Simon 2010-06-09 09:15:50

+0

对不起,我误读了文档,实际上我看不到你的代码存在问题,你是否在startDownload方法中设置了断点,并检查是否一切正常? – Alfonso 2010-06-09 14:55:17

0

看看这里:http://www.depl0y.com/?p=345 也许会有所帮助。

编辑:是的,正在为我工​​作。让我知道你是否也在为你工作,或者你需要更多的信息。

0

我有同样的问题。此外,我几乎使用相同的代码(它来自苹果示例LazyTableImages)。

虽然Apple的测试项目中的代码有效,但它并未在我的项目中运行 - 尽管我只是制作了Apple代码的副本。

我发现的是:当我用

NSLog(@"Is%@ main thread", ([NSThread isMainThread] ? @"" : @" NOT")); 
中的cellForRowAtIndexPath

:以及IconDownload.m的startDownload:(两个项目),我发现它是苹果的样品中的主线程,但不是我的代码中的主线程。

这可能是问题所在。

任何想法如何解决?


编辑!解决了 !

我只是在使用的cellForRowAtIndexPath

NSDictionary *info = [NSDictionary dictionaryWithObjectsAndKeys:entry.imageURL, @"imageURL", indexPath, @"indexPath", nil]; 
[self performSelectorOnMainThread:@selector(startIconDownload:) withObject:info waitUntilDone:NO]; 

被迫主线:您将需要一个字典多个参数发送至方法。

你可以在你的代码中做类似的解决方案。我的代码

[self startIconDownload:feedRecord forIndexPath:indexPath]; 

和修改startIconDownload:替换行这样

- (void)startIconDownload:(NSDictionary *)info 
{ 
    NSString *url = [info objectForKey:@"imageURL"]; 
    NSIndexPath *indexPath = [info objectForKey:@"indexPath"]; 
    ... 
} 

有些变量我在你的应用程序不同。

但我只是不明白为什么它在苹果的示例中没有强制主线程。

有什么想法?

1

您可以使用此代码

[tableView performSelector:@selector(reloadData) onThread:[NSThread mainThread] withObject:nil waitUntilDone:YES]; 

代替

[tableView reloadData]; 
1

你不叫NSURLConnection的开始方法对象在您startDownload方法创建。

一定要做到这一点:

- (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