2010-06-09 39 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