【问题标题】:Click To Add Image To Core Data单击以将图像添加到核心数据
【发布时间】:2014-05-22 00:29:02
【问题描述】:

我正在开发一个使用核心数据的应用程序,到目前为止一切正常。但我还没有在其中使用图像。我想这样做,但我不知道从哪里开始。我想让用户单击一个按钮,让他们可以选择获取图像的位置。此外,是否可以让用户只输入图像的 URL 并将其保存到核心数据中?就是这样,所以如果有人能指出我正确的方向,我将不胜感激。谢谢!

到目前为止我的代码:https://github.com/jackintosh7/Core-Data

【问题讨论】:

    标签: ios objective-c core-data uiimageview


    【解决方案1】:

    编辑 - 我更新了 saveImgData:fromURL 中的一些引用以匹配方法中传递的参数。我在 NSURL 协议中使用了这种方法的变体来拦截请求并缓存特定的请求。某些实体参数可能不适用于您的问题。忽略那些(例如 encoding/lastModified/mimeType/response)。

    要将图像保存到 CoreData 试试这个。

    首先,下载您的图像。用户可以在文本输入字段中输入 url。 (andrewbuilder 列出的示例可以正常工作)

    NSURL *imgURL = [NSURL URLWithString:myImgURL];
    NSData *imgData = [NSData dataWithContentsOfURL:imgURL];
    
    //a better way would be to do this asynchronously. Google "Lazy Image Loading" and
    //you should find a suitable example app from Apple
    

    设置您的 CoreData 实体以存储图像数据。这是一个示例,它不仅存储图像二进制数据。

    然后将您的图像数据直接保存到 CoreData。 我有一个 CoreData 管理器类,但您可能在 AppDelegate 中有您的 CoreData 堆栈,这是 Apple 设置它们的方式。

    -(void)saveImgData:(NSData*)myImgData fromURL:(NSString*)urlStr{
    
        //If you have a CoreData manager class do something like this
        CoreDataManager *cdm = [CoreDataManager defaultManager];
        //Use private queue concurrency type for background saving
        NSManagedObjectContext *ctx  = [[NSManagedObjectContext alloc]initWithConcurrencyType:NSPrivateQueueConcurrencyType];
        //Set up the parent context, in this case is the mainMOC
        //If you are using basic CoreData it would be the managedObjectContext on your AppDelegate
        ctx.parentContext = cdm.mainMOC;
    
        [ctx performBlock:^{
            //performBlock executes on a background thread
            CachedURLResponse *cacheResponse = [NSEntityDescription insertNewObjectForEntityForName:@"CachedURLResponse" inManagedObjectContext:ctx];
            cacheResponse.relativeURLHash = [NSNumber numberWithInteger:[urlStr hash]];
            cacheResponse.data = [myImgData copy];
            cacheResponse.response = [NSKeyedArchiver archivedDataWithRootObject:self.response];
            cacheResponse.url = [urlStr copy];
            cacheResponse.timestamp = [NSDate date];
            cacheResponse.mimeType = [self.response.MIMEType copy];
            cacheResponse.encoding = [self.response.textEncodingName copy];
            if ([self.headers objectForKey:@"Last-Modified"])
                cacheResponse.lastModified = [self.headers objectForKey:@"Last-Modified"];
    
            NSError *__block error;
            if (![ctx save:&error])
                NSLog(@"Error, Cache not saved: %@", error.userInfo);
    
            [cdm.mainMOC performBlockAndWait: ^{
                [cdm saveContext];
            }];
    
        }];
    }
    

    我的 CoreDataManager.h 看起来像这样:

    我的 CoreDataManager.m 文件如下所示:

    #import "CoreDataManager.h"
    #import <CoreData/CoreData.h>
    @implementation CoreDataManager
    
    @synthesize mainMOC = _mainMOC,
            managedObjectModel = _mom,
            persistentStoreCoordinator = _psc
    ;
    
    
    +(CoreDataManager*)defaultManager
    {
        static CoreDataManager *_defaultMgr = nil;
    
            static dispatch_once_t oncePred;
            dispatch_once(&oncePred, ^{
                _defaultMgr = [[CoreDataManager alloc] init];
            });
    
        return _defaultMgr;
    
    }
    
    
    
    -(id)init
    {
        if (self = [super init])
        {
            NSError *error = nil;
            NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"MyDatabase.sqlite"];
            NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"MyDataModelName" withExtension:@"momd"];
    
            _mom = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
            _psc = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];
            if (![_psc addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:&error])
                NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
    
            _mainMOC = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
            [_mainMOC setPersistentStoreCoordinator:self.persistentStoreCoordinator];
    
        }
        return self;
    }
    
    
    - (void)saveContext
    {
        NSError *error = nil;
        if (self.mainMOC != nil && ([self.mainMOC hasChanges] && ![self.mainMOC save:&error])) {
            NSLog(@"CoreData save error: %@, %@", error, [error userInfo]);
        }
    }
    
    
    #pragma mark - Core Data Stack
    
    - (NSManagedObjectContext *)mainMOC
    {
        return _mainMOC;
    }
    
    - (NSManagedObjectModel *)managedObjectModel
    {
        return _mom;
    }
    
    - (NSPersistentStoreCoordinator *)persistentStoreCoordinator
    {
        return _psc;
    }
    
    - (NSURL *)applicationDocumentsDirectory
    {
        return [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
    }
    
    
    
    
    @end
    

    希望这能给你一个好的起点。谷歌“CoreData 类参考”以获得关于该主题的一些非常好的阅读。

    【讨论】:

      【解决方案2】:

      我从 Paul Hegarty 出色的 iTunes U/Stanford Uni 讲座中学到了很多……他的最新课程名为“Developing iOS Apps for iPhone and iPad”,他的一些讲座专门针对 Core Data 中图像的使用。对于您想做的事情,我建议您观看第 10-13 课,但确实值得观看整个系列。

      除此之外,请花一些时间阅读 Apple 关于 Core Data 的文档,从 here 开始。 Samir 对此堆栈溢出 question 写了一个很好的响应。

      在如何实现代码方面,您有几个选择。虽然 Core Data 能够管理将图像保存到持久数据存储结构(例如 sqlite)中,但重要的是要注意大图像文件会减慢获取过程。

      Core Data 可以为您管理如何存储图像...通过单击 Data Model Inspector 中的 Allows External Storage 选项...参见下面的附图。

      但是,如果您希望将用户指向一个 URL,则可能值得考虑向您的实体 Item 添加(另一个单独的)属性,例如名为 pictureURL 的属性。

      使用UIViewController 中的属性来管理实体属性...

      @property (nonatomic, retain) NSString * pictureURL;

      然后您可以将UITextField 添加到UIViewController 以接受用户对此属性pictureURL 的输入。

      当你有一个图片的 URL 时,你可以用类似这样的“getter”代码返回图片(其中UIImageUIViewController 的一个属性)...

      - (UIImage *)image {
          NSURL *imageURL = [NSURL URLWithString:self.pictureURL];
          NSData *imageData = [NSData dataWithContentsOfURL:imageURL];
          return [UIImage imageWithData:imageData];
      }
      

      希望能给你一些方向。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-12-18
        • 1970-01-01
        • 2012-05-05
        • 1970-01-01
        • 2021-10-21
        • 1970-01-01
        • 1970-01-01
        • 2012-09-27
        相关资源
        最近更新 更多