我使用以下方法更新表格 View 单元格:
- (void)imageDownloaderSDWebImageDownloader *)downloader didFinishWithIndexPathNSIndexPath *)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 的委托(delegate),更新时收到错误:
thread9: Program received signal: "SIGABRT".
Form the device console, there is:
: *** 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)
Then I print the arr which holds the current visible index path:
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]"
)
and the received indexPath
2 indexes [0, 7]
The indexPath is included in the visible index path, and why it still cause the NSRangeException ?
It looks like a bug for cellForRowAtIndexPath:indexPath , as the row of index path is 7 which is beyond the visible index path arr, am I right?
Add the eatableview delegate method:
- (UITableViewCell *)tableViewUITableView *)inTableView cellForRowAtIndexPathNSIndexPath *)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;
}
添加于 11-17:
当“SIGABRT”收到时,documentDirectoryFileList 有对象,例如 30+。接收到的 indexPath 存在于可见索引路径数组中。但我注意到:滚动表格 View 时很容易发生。没有新对象添加到数据源。我所做的只是更新单元格上的图像。
我猜可能是:
当接收到的索引路径开始更新相应的单元格时,我碰巧滚动它并且单元格或索引路径不再可见。然后它崩溃了。
Best Answer-推荐答案 strong>
这似乎是多线程的一种问题。
- (void)imageDownloaderSDWebImageDownloader *)downloader didFinishWithIndexPathNSIndexPath *)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)imageDownloaderSDWebImageDownloader *)downloader didFinishWithIndexPathNSIndexPath *)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
}
}
}
关于ios - uitableview 更新错误,我们在Stack Overflow上找到一个类似的问题:
https://stackoverflow.com/questions/8148811/
|