从核心数据记录在 uiwebview 中显示图像

Posted

技术标签:

【中文标题】从核心数据记录在 uiwebview 中显示图像【英文标题】:Displaying images in uiwebview from core data record 【发布时间】:2011-10-01 19:02:08 【问题描述】:

所以我有一个我为 iPad 编写的应用程序,我希望能够允许用户通过从相册或相机中选择图像来将图像插入到他们的文档中。所有这些都很好。因为用户保存文档的时间可能比他们保存在相册中的图像的时间长,所以我制作了一个副本,将其缩小一点,然后将其存储在一个仅用于此目的的核心数据表中。

我这样存储图像:

NSManagedObjectContext* moc=[(ActionNote3AppDelegate *)[[UIApplication sharedApplication] delegate] managedObjectContext];
NSString* imageName=[NSString stringWithFormat:@"img%lf.png",[NSDate  timeIntervalSinceReferenceDate]];
Image* anImage = [NSEntityDescription insertNewObjectForEntityForName:@"Image" inManagedObjectContext:moc];
anImage.imageName=imageName;
anImage.imageData=UIImagePNGRepresentation(theImage);
NSError* error=nil;
if(![moc save:&error]) ...

按照Cocoa With Love 的建议,我将 NSURLCache 子类化,并因此覆盖 cachedResponseForRequest:

- (NSCachedURLResponse *)cachedResponseForRequest:(NSURLRequest *)request 
    NSString *pathString = [[[request URL] absoluteString]lastPathComponent];
    NSData* data = [Image dataForImage:pathString];
    if (!data) 
        return [super cachedResponseForRequest:request];
    

    NSURLResponse *response =[[[NSURLResponse alloc] 
                               initWithURL:[request URL] 
                               MIMEType:[NSString stringWithString:@"image/png"] 
                               expectedContentLength:[data length] 
                               textEncodingName:nil] 
                              autorelease];
    NSCachedURLResponse* cachedResponse =[[[NSCachedURLResponse alloc] initWithResponse:response data:data] autorelease];

    return cachedResponse;

我还通过在 didFinishLaunchingWithOptions 的应用委托中执行此操作来确保应用使用子类 NSURLCache:

ANNSUrlCache* uCache=[[ANNSUrlCache alloc]init];
[NSURLCache setSharedURLCache:uCache];

从核心数据记录返回图像数据的方法如下:

+(NSData*)dataForImage:(NSString *)name 
    NSData* retval=nil;
    NSManagedObjectContext* moc=[(ActionNote3AppDelegate *)[[UIApplication sharedApplication] delegate] managedObjectContext];

    NSEntityDescription *entityDescription = [NSEntityDescription entityForName:@"Image" inManagedObjectContext:moc];
    NSFetchRequest *request = [[[NSFetchRequest alloc] init] autorelease];
[request setEntity:entityDescription];

    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"imageName==%@", name];
[request setPredicate:predicate];

    NSError* error=nil;
    NSArray *array = [moc executeFetchRequest:request error:&error];

    if ([array count]>0) 
        retval=((Image*)[array objectAtIndex:0]).imageData;
    

    return retval;

为了将图像插入 Web 视图,我有一个 html img 标签,其中 src="" 中的名称与图像表中的名称相关联。上面 NSURLCache 代码的重点是观察我们存储在图像表中的名称,截取它,然后为请求的图像发​​送实际的图像数据。

当我运行它时,我看到在我的子类 NSURLCache 对象中请求图像。它正在寻找正确的记录,并按应有的方式返回数据。但是,我的 uiwebview 中仍然出现未找到图像的图标:

所以 Marcus(下)建议我不要将图像数据存储在核心数据表中。所以我做了一些改变来适应:

存储图像:

NSString* iName=[NSString stringWithFormat:@"img%lf.png",[NSDate timeIntervalSinceReferenceDate]];
NSData* iData=UIImagePNGRepresentation(theImage);

NSArray* paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString* documentsDirectory = [paths objectAtIndex:0];
NSString* fullPathToFile = [documentsDirectory stringByAppendingPathComponent:iName];
[iData writeToFile:fullPathToFile atomically:NO];

检索图像:

- (NSCachedURLResponse *)cachedResponseForRequest:(NSURLRequest *)request 
    NSString *pathString = [[[request URL] absoluteString]lastPathComponent];
    NSString* iPath = [Image pathForImage:pathString];
    if (!iPath) 
        return [super cachedResponseForRequest:request];
    

    NSData* idata=[NSData dataWithContentsOfFile:iPath];

    NSURLResponse *response =[[[NSURLResponse alloc] 
                               initWithURL:[request URL] 
                               MIMEType:@"image/png" 
                               expectedContentLength:[idata length] 
                               textEncodingName:nil] 
                              autorelease];
    NSCachedURLResponse* cachedResponse =[[[NSCachedURLResponse alloc] initWithResponse:response data:idata] autorelease];

    return cachedResponse;

在调试模式下,我看到 idata 确实加载了正确的图像数据。

我仍然得到图像未找到的图像!显然,我在这里做错了什么。我只是不知道它是什么。

那么...我在这里做错了什么?我怎样才能让它正常工作?

谢谢。

【问题讨论】:

你如何尝试将图像放入 UIWebView?在您的代码中看不到。 @Tom - 我已编辑以包含相关信息。基本上是一个 img 标签,其中 src 中的名称是图像文件中使用的名称。 img 标签在 html 到达 UIWebView 之前被插入到 html 中。 【参考方案1】:

我会强烈建议您不要将二进制数据存储在 Core Data 中。在 Core Data 中存储二进制数据,尤其是在 ios 设备上,会导致缓存出现严重的性能问题。

首选方法是将实际二进制数据存储在磁盘上的文件中,并引用存储在 Core Data 中的文件。从那里可以将图像 url 更改为指向本地文件是一件简单的事情。

【讨论】:

我确实尝试过,实际上。我已经编辑了我的问题以包含代码详细信息。我猜我在某个地方做了一些愚蠢的事情,因为它仍然不起作用。谢谢。 我没有看到任何跳出的东西。您是否有针对此行为的测试项目?我发现一个测试非常好有几个原因:1)我们可以修改它,2)它隔离代码,你通常可以自己发现问题,3)如果它是一个 Apple 错误,你的雷达已经完成 :) 【参考方案2】:

所以事实证明我想太多了。当我编写 HTML 时,我只是将图像的路径与图像标签一起写入。奇迹般有效。

不过,我很想知道为什么我在问题中提出的解决方案不起作用。

而且,我确实没有将图像存储在表格中。

【讨论】:

以上是关于从核心数据记录在 uiwebview 中显示图像的主要内容,如果未能解决你的问题,请参考以下文章

如何从 iOS 照片库中获取图像并在 UIWebView 中显示

UIWebView 使用 loadData 编译错误

ARKit 显示损坏的 UIWebView

在不使用 UIWebview 的情况下显示 gif 图像 [重复]

从 uiimagepicker 上传 uiwebview 中的图像

在 UIwebview 中加载本地图像