2011-11-16 49 views
2

我使用下面的方法更新表視圖細胞:UITableView的更新錯誤


- (void)imageDownloader:(SDWebImageDownloader *)downloader didFinishWithIndexPath:(NSIndexPath *)indexPath 
{ 
    NSArray *arr = [self.tableView indexPathsForVisibleRows]; 
    if ([arr containsObject:indexPath]) 
    { 
     UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:indexPath];//received error here 
     UIImageView *imageView = (UIImageView *)[cell viewWithTag:'ICON']; 
     SDWebImageManager *manager = [SDWebImageManager sharedManager]; 
     UIImage *image = [manager imageWithURL:downloader.url]; 
     imageView.image = image; 
    } 
} 

這是SDWebImageDownloader委託接收的錯誤時更新:

 
thread9: Program received signal: "SIGABRT". 

形成該裝置控制檯,有:

 
: *** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSArrayM objectAtIndex:]: index 7 beyond bounds [0 .. 6]' 
    *** First throw call stack: 
    (0x335a38bf 0x300971e5 0x334ecb6b 0x30ff0eb1 0xaa0a7 0x334fd435 0xb5b13 0x30d91a91 0x30e255a1 0x36fa0c1d 0x36fa0ad8) 

然後我打印arr它包含當前可見索引路徑:

 
Printing description of arr: 
(
    " 2 indexes [0, 1]", 
    " 2 indexes [0, 2]", 
    " 2 indexes [0, 3]", 
    " 2 indexes [0, 4]", 
    " 2 indexes [0, 5]", 
    " 2 indexes [0, 6]", 
    " 2 indexes [0, 7]" 
) 

和接收indexPath

 
2 indexes [0, 7] 

的indexPath包括在可見的索引路徑,以及爲什麼它仍然會造成NSRangeException? 它看起來像cellForRowAtIndexPath:indexPath的錯誤,因爲索引路徑的行是7,超出了可見的索引路徑arr,對嗎?

添加eatableview委託方法:在11-17


- (UITableViewCell *)tableView:(UITableView *)inTableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 
{ 
    static NSString *CellIdentifier = @"Cell"; 

    NSString *path; 
    NSString *filename; 

    BOOL download = YES; 
    NSDictionary *tempDic = nil; 
    @synchronized (documentDirectoryFileList) { 
     tempDic = [self.documentDirectoryFileList objectAtIndex:indexPath.row]; 
     filename = [tempDic objectForKey:@"filename" ]; 

     NSURL *url = [tempDic objectForKey:@"url" ]; 
     if (url) { 
      path = [ url path ]; 
      download= [ self downloadedFile:url ]; 

     } else { 

       path = [tempDic objectForKey:@"filepath" ]; 
     } 
    } 

    BOOL isDirectory = FALSE; 

    NSFileManager *fileManager = [[NSFileManager alloc] init]; 
    BOOL found = [fileManager fileExistsAtPath: path isDirectory: &isDirectory]; 

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; 
    if (cell == nil) { 
     cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease]; 

     CGRect rect; 
     rect = CGRectMake(5,14, 32, 32); 

     cell.userInteractionEnabled = YES; 

     UIImageView *imageView = [[UIImageView alloc] initWithFrame:rect]; 
     imageView.tag = 'ICON'; 
     [cell.contentView addSubview:imageView]; 
     [imageView release];   

     rect = CGRectMake(42, 10, 238, 22); 

     UILabel *labelView = [[UILabel alloc] initWithFrame:rect]; 
     labelView.tag = 'NAME'; 
     labelView.font = [UIFont boldSystemFontOfSize:18]; 
     if (download == NO) 
      labelView.textColor = [UIColor lightGrayColor ]; 
     [cell.contentView addSubview:labelView]; 
     [labelView release]; 

     rect = CGRectMake(42, 34, 200, 20); 
     labelView = [[UILabel alloc] initWithFrame:rect]; 
     labelView.tag = 'TIME'; 
     labelView.font = [UIFont systemFontOfSize:12]; 
     if (download == NO) 
      labelView.textColor = [UIColor lightGrayColor ]; 
     [cell.contentView addSubview:labelView]; 
     [labelView release]; 

     rect = CGRectMake(200, 34, 75, 20); 
     labelView = [[UILabel alloc] initWithFrame:rect]; 
     labelView.tag = 'SIZE'; 
     labelView.font = [UIFont systemFontOfSize:12]; 
     if (download == NO) 
      labelView.textColor = [UIColor lightGrayColor ]; 
     labelView.textAlignment = UITextAlignmentRight; 
     [cell.contentView addSubview:labelView]; 
     [labelView release]; 

    } 


    // Get the time zone wrapper for the row 
    UIImageView *imageView = (UIImageView *)[cell viewWithTag:'ICON']; 
    imageView.image = NULL; 

    NSString* extension = [[path pathExtension] lowercaseString]; 
    if ([extension isEqualToString: @"png"] || 
     [extension isEqualToString: @"jpg"] || 
     [extension isEqualToString: @"jpeg"] || 
     [extension isEqualToString: @"bmp"] || 
     [extension isEqualToString: @"gif"] || 
     [extension isEqualToString: @"tiff"] || 
     [extension isEqualToString: @"thm"]) 
    { 
     NSString *realFilePath = [ fileManager destinationOfSymbolicLinkAtPath:path error:nil ]; 
     if (realFilePath) 
      path = realFilePath; 

     NSURL *url = [[NSURL fileURLWithPath:path] URLByAppendingPathComponent:@"thumb.th"]; 
     SDWebImageManager *manager = [SDWebImageManager sharedManager]; 
     UIImage *temp = [manager imageWithURL:url]; 
     if (temp) { 
      imageView.image = temp; 
     } 
     else 
     { 
      SDWebImageDownloader *downloader = [SDWebImageDownloader downloaderWithURL:url delegate:self indexPath:indexPath]; 
     } 

    } else { 

     imageView.image = [ self determineFileIcon : path ]; 

    } 

    // Configure the cell. 
    UILabel *labelView = (UILabel *)[cell viewWithTag:'NAME']; 
    labelView.text = filename; 
    cell.accessoryType = UITableViewCellAccessoryDetailDisclosureButton; 
    if (isDirectory) { 
     if (isLink(path)) 
      labelView.font = [UIFont italicSystemFontOfSize:16.0]; 
     else 
      labelView.font = [UIFont boldSystemFontOfSize:16.0]; 
    } else { 
     if (isLink(path)) 
      labelView.font = [UIFont italicSystemFontOfSize:16.0]; 
     else 
      labelView.font = [UIFont systemFontOfSize:16.0]; 
    } 

    labelView = (UILabel *)[cell viewWithTag:'TIME']; 
    NSCalendar *theCalendar= [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar]; 
    NSCalendarUnit unitFlags = NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit | NSHourCalendarUnit | NSMinuteCalendarUnit | NSSecondCalendarUnit; 

    NSDate *date = [tempDic objectForKey:@"date" ]; 
    NSDateComponents *dateComponents = [theCalendar components:unitFlags fromDate:date]; 

    NSInteger year = [dateComponents year]; 
    NSInteger month = [dateComponents month]; 
    NSInteger day = [dateComponents day]; 
    NSInteger hour = [dateComponents hour]; 
    NSInteger minute = [dateComponents minute]; 
    NSInteger second = [dateComponents second]; 

    [theCalendar release]; 
    labelView.text = [NSString stringWithFormat:@"%d/%02d/%02d %02d:%02d:%02d", year,month,day,hour,minute,second ]; 

    if (!isDirectory) { 
     labelView = (UILabel *)[cell viewWithTag:'SIZE']; 
     [labelView setHidden:NO]; 
     NSNumber *size = [tempDic objectForKey:@"filesize" ]; 
     float value = [ size floatValue ]; 
     NSString *str; 
     if (value > (1024*1024)) { 
      value = value/1024/1024; 
      str = [NSString stringWithFormat:@"%0.1f MB", value ]; 
     } else if (value > 1024) { 
      value = value/1024; 
      str = [NSString stringWithFormat:@"%0.1f KB", value ]; 
     } else { 
      str = [NSString stringWithFormat:@"%d Bytes", [ size integerValue ] ]; 
     } 
     labelView.text = str; 
    } 
    else 
    { 
     labelView = (UILabel *)[cell viewWithTag:'SIZE']; 
     [labelView setHidden:YES]; 
    } 

    [fileManager release]; 

    return cell; 
} 

加了: 當 「SIGABRT」 接收,所述documentDirectoryFileList有物體,例如30+。收到的indexPath存在於可見索引路徑數組中。但我注意到:當我滾動tableview時很容易發生。沒有新的對象添加到數據源。我所做的只是更新單元格上的圖像。

我想它可能是: 當收到的索引路徑開始更新相應的單元格時,我恰好滾動它並且單元格或索引路徑不再可見。然後它崩潰。

+0

是的,你是對的。發佈你的'cellForRowAtIndexPath:indexPath'。我們將檢查它 – Nekto

+1

你在 返回什麼' - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section'? –

+0

@ Nekto,謝謝。我補充說。 – scorpiozj

回答

4

這似乎是一種關於多線程的問題。


- (void)imageDownloader:(SDWebImageDownloader *)downloader didFinishWithIndexPath:(NSIndexPath *)indexPath 
{ 


    @synchronized(tableView) 
    { 
     NSArray *arr = [self.tableView indexPathsForVisibleRows]; 
     if ([arr containsObject:indexPath]) 
     { 

      UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:indexPath]; 
      if (!cell) 
      { 
       return; 
      } 

      UIImageView *imageView = (UIImageView *)[cell viewWithTag:'ICON']; 
      SDWebImageManager *manager = [SDWebImageManager sharedManager]; 
      UIImage *image = [manager imageWithURL:downloader.url]; 
      if (image) { 
       dispatch_async(dispatch_get_main_queue(), ^{ 
        imageView.image = image; 
       }); 

      } 
     } 

    } 
} 

,或者你可以

 

- (void)imageDownloader:(SDWebImageDownloader *)downloader didFinishWithIndexPath:(NSIndexPath *)indexPath 
{ 


    @synchronized(tableView) 
    { 
     NSArray *arr = [self.tableView indexPathsForVisibleRows]; 
     if ([arr containsObject:indexPath]) 
     { 

      dispatch_async(dispatch_get_main_queue(), ^{ 
        [self.tableView reloadRowsAtIndexPaths:[NSArray arrayWithObjects:indexPath, nil] withRowAnimation:UITableViewRowAnimationNone]; 
       });//must be in main thread; reloadRowsAtIndexPaths: is not thread safe 



     } 

    } 
} 
+0

我也遇到了同樣的問題。您的修復程序正在爲我工​​作。但我不知道爲什麼會發生這種情況。你能解釋一下嗎? –