每次滚动后,图像在tableview中发生变化

时间:2013-11-20 09:38:40

标签: ios multithreading uitableview asynchronous

嗨,我对IOS很陌生,所以原谅愚蠢的问题。我正在开发一个在桌面视图中加载大图像的应用程序。我正在异步获取本地图像并存储到字典中以进行缓存问题是当我滚动tableview图像更改并调整延迟时,如果我添加更多图像并滚动大量时间,应用程序本身会崩溃
这是我的代码:

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

    UITableViewCell *cell =
        (UITableViewCell *) [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

    if (cell == nil) {
        cell =
            [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle
                                   reuseIdentifier:CellIdentifier];
    }
      NSError *attributesError = nil;

    NSString *workSpacePath = [[self applicationDocumentsDirectory]
                            stringByAppendingPathComponent:[images objectAtIndex:indexPath.row]];
    NSDictionary *fileAttributes = [[NSFileManager defaultManager]
                                 attributesOfItemAtPath:workSpacePath error:&attributesError];
    NSNumber * fileSizeNumber = [fileAttributes objectForKey:NSFileSize];
    long long int fileKBSize = [fileSizeNumber longLongValue]/1024;

   cell.textLabel.backgroundColor = [UIColor clearColor];
    NSString *descriptionString =  [images objectAtIndex:indexPath.row];
    NSLog(@"descriptionString :%@",descriptionString);
    if ([[despDectionary objectForKey:descriptionString] length] > 0) {
            cell.detailTextLabel.text = [NSString stringWithFormat:@"%@",[despDectionary objectForKey:descriptionString]];
    }
    else {
            cell.detailTextLabel.text = @"File Description";
    }

    if([self.cacheImages objectForKey:descriptionString]!=nil)
    {
     cell.imageView.image = [self.cacheImages valueForKey:descriptionString];
    }

    else
    {
    dispatch_queue_t bg = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0ul);

    dispatch_async(bg,^{

    UIImage *myimage=[UIImage imageWithData:[NSData dataWithContentsOfFile:workSpacePath]];

   NSData *imageData = UIImageJPEGRepresentation(myimage, 0.2);
    UIImage *image = [UIImage imageWithData:imageData];
    UIImage *thumb = [image makethumbnail:CGSizeMake(110, 70)];
    dispatch_async(dispatch_get_main_queue(), ^{
   // [cell.setNeedsLayout];
     cell.imageView.frame = CGRectMake(0, 0, 110, 70);
    if([tableView indexPathForCell:cell].row== indexPath.row)
    {
    //cell.imageView.frame = CGRectMake(0, 0, 110, 70);
    NSString *imagename = [NSString stringWithFormat:@"%@",[despDectionary objectForKey:descriptionString]];
     [self.cacheImages setValue:thumb forKey:imagename];
           cell.imageView.frame = CGRectMake(0, 0, 110, 70);
      NSLog(@"cacheImages -- %@",self.cacheImages);
    cell.imageView.image = [self.cacheImages valueForKey:imagename];
   // [tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationNone];
    }//[tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationNone];
      });
    });
  }
  // NSLog(@" Dictionary CACHE IMAGES is @%",self.cacheImages);
    cell.detailTextLabel.backgroundColor = [UIColor clearColor];
    cell.selectionStyle = UITableViewCellSelectionStyleNone;

    UIButton * button = [UIButton buttonWithType:UIButtonTypeCustom];
    button.frame = CGRectMake(250, 0, 49,56);
    [button setImage:[UIImage imageNamed:@"deletButotn.png"] forState:UIControlStateNormal];
    button.tag = indexPath.row;
    [button addTarget:self action:@selector(deleteButtonAction:)  forControlEvents:UIControlEventTouchUpInside];
    [cell.contentView addSubview:button];


    return  cell;
} 

2 个答案:

答案 0 :(得分:1)

我建议使用SDWebimage来管理它......这么容易且一致。

https://github.com/rs/SDWebImage

答案 1 :(得分:0)

使用直接存储图像的NSCacheNSDictionary - 特别是如果您使用它是异步的,这非常昂贵。您可以使用Profile Instruments您的应用,并查看是否存在内存泄漏或分配问题。我认为你可能会遇到太多的分配问题。

作为解决方案,我建议您使用NSDictionaryNSCache来存储不是图片,而是存储图片路径。您还可以使用NSOperation从缓存变量中存储的路径中获取图像。顺便说一句,你会异步获得图像。

例如,有一个创建的ImageRecord类,其中包含图像路径 imageID 。在该类中,我们有一个从磁盘获取图像的函数。尽管如此,可以异步或NSOperation调用该函数:

@implementation ImageRecord

NSString *filePath;
NSString *imageID;
// Ignoring getters, setters and other functions

// Here is our function :
-(UIImage *)getImageFromDisk{
    UIImage *image = [UIImage new];
    NSData *data = [NSData dataWithContentsOfMappedFile:self.filePath];
    if (data) {
        image = [UIImage imageWithData:data];
        if (!image) {
            return nil;
        }
    }
    return image;
}

并在cellForRowAtIndexPath函数中:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (!cell) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
    }
    // example caching variable: We have a list of imageRecords with ID's and filePaths 
    // We're using indexPath as imageID of imageRecord
    imagesCache = (NSDictionary *) [self getImagesCache]
    ImageRecord *aRecord = [imagesCache objectForKey:indexPath.row];
    // I didn't call directly but you can try to call the function asynchronously.
    cell.imageView.image  = [aRecord getImageFromDisk];
    return cell;
}

会有语法错误,我很抱歉,但我希望示例的逻辑对您有所帮助以克服这个问题