如何将NSCache与CoreData一起使用

时间:2013-12-11 12:25:12

标签: multithreading grand-central-dispatch nsoperation nsoperationqueue nscache

我开发了一个项目,用户在画布上绘制图像,我使用CoreData将其存储在文件中,我有一对多的关系称为文件夹到文件。所以这里都是图像。我从文件中检索图像,根据我的表格单元格高度调整大小并将其显示在桌面上。一旦显示,我想缓存图像。

我在文件夹单元格上也有一些标签,它给我一些关于我的文件的信息,我在飞行中更新。 我也会刷细胞以将其标记为完整并将其移至细胞的底部。

我还会根据用户查询的方式在不同的视图中显示相同的文件图像。

我想知道最好的方法,我通过网络阅读,他们有很多方法,GCD,NSOperationQueues等等。

哪种方法最适合我。

我想展示一些代码

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

    FolderCell *tableCell = (FolderCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];

    if (tableCell == nil)
    {
        NSArray *nib = [[NSBundle mainBundle] loadNibNamed:@"FolderCell" owner:self options:nil];
        tableCell = [nib objectAtIndex:0];
    }

    NSMutableArray *categoryArray = [[self.controller fetchedObjects]mutableCopy];

    Folder *category = [categoryArray objectAtIndex:[indexPath row]];

    [tableCell configureCellWithNote:category]; //This function is written in my FolderCell.m function        

}
    return tableCell; 
}


-(void)configureCellWithNote:(Folder *)category
{    
    self.category = category;


    UIImage *image1 = [UIImage imageWithData:category.noteImage];
    CGSize newSize;


    if(image1.size.width == 620 && image1.size.height == 200)
   {              
       newSize = CGSizeMake(300, 97);
   }     

    UIGraphicsBeginImageContextWithOptions(newSize, NO, 0.0);

    [image1 drawInRect:CGRectMake(0,0,newSize.width,newSize.height)];


    UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();

    UIGraphicsEndImageContext();     

    self.notesImage.image = newImage;    
 }

所以这里发生的事情是configureCellWithNote需要花费大量时间,因为它正在调整图像大小。请帮我决定如何解决这个性能问题。

此致 Rajit

1 个答案:

答案 0 :(得分:1)

如果您只是想将调整大小操作随机播放到后台线程,您可以这样做:

- (void)configureCellWithNote:(Folder *)category
{
    self.category = category;

    UIImage *image1 = [UIImage imageWithData:category.noteImage];
    CGSize newSize;

    if(image1.size.width == 620 && image1.size.height == 200)
    {
        newSize = CGSizeMake(300, 97);
    }

    dispatch_async(dispatch_get_global_queue(0,0), ^{
        UIGraphicsBeginImageContextWithOptions(newSize, NO, 0.0);

        [image1 drawInRect:CGRectMake(0,0,newSize.width,newSize.height)];

        UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();

        UIGraphicsEndImageContext();

        dispatch_async(dispatch_get_main_queue(), ^{
            self.notesImage.image = newImage;
        });
    });

}

如果你想缓存结果,那么技巧就是提出一个好的缓存密钥。不幸的是,很难说你发布了什么会成为一个好的缓存密钥。当然它需要包括大小,但它还需要包含一些将它与类别联系起来的东西。我想如果没有其他任何你可以使用NSManagedObjectID作为类别,但我认为这将特定于你拥有的每个托管对象上下文。假设Folder上有一个名为uniqueName的属性,缓存实现可能如下所示:

- (UIImage*)imageForCategory: (Folder*)category atSize: (CGSize)size
{
    // A shared (i.e. global, but scoped to this function) cache
    static NSCache* imageCache = nil;
    // The following initializes the cache once, and only once
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        imageCache = [[NSCache alloc] init];
    });

    // Generate a cache key sufficient to uniquely identify the image we're looking for
    NSString* cacheKey = [NSString stringWithFormat: @"%@|%@", category.uniqueName, NSStringFromSize((NSSize)size)];
    // Try fetching any existing image for that key from the cache.
    UIImage* img = [imageCache objectForKey: cacheKey];

    // If we don't find a pre-existing one, create one
    if (!img)
    {
        // Your original code for creating a resized image...
        UIGraphicsBeginImageContextWithOptions(size, NO, 0.0);
        UIImage* image1 = [UIImage imageWithData:category.noteImage];
        [image1 drawInRect:CGRectMake(0,0,size.width,size.height)];
        img = UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();

        // Now add the newly-created image to the cache 
        [imageCache setObject: img forKey: cacheKey];
    }

    // Return the image 
    return img;
}