Сохранение и получение UIImage в CoreData

В моем приложении я пытаюсь сохранить и получить изображение в основных данных. Я могу успешно сохранить изображение после соглашения UIimage в NSData, но когда я пытаюсь получить изображение как NSData, он показывает вывод, как указано ниже,

случай 1: при попытке отобразить в виде строки из БД.

 <Event: 0x5b5d610> (entity: Event; id: 0x5b5ce30 <x-coredata://F51BBF1D-6484-4EB6-8583-147E23D9FF7B/Event/p1> ; data: <fault>)

случай 2: при попытке отобразить как данные

 [Event length]: unrecognized selector sent to instance 0x5b3a9c0
 2010-07-28 19:11:59.610 IMG_REF[10787:207] *** Terminating app due to uncaught exception    'NSInvalidArgumentException', reason: '-[Event length]: unrecognized selector sent to instance 0x5b3a9c0'

Мой код,

to save:

NSManagedObjectContext *context = [self managedObjectContext];

newsObj = [NSEntityDescription insertNewObjectForEntityForName:@"Event" inManagedObjectContext:context];

NSURL *url = [NSURL URLWithString:@"http://www.cimgf.com/images/photo.PNG"];

NSData *data = [[NSData alloc] initWithContentsOfURL:url];

uiImage = [UIImage imageWithData:data];

NSData * imageData = UIImagePNGRepresentation(uiImage);

[newsObj setValue:imageData forKey:@"imgPng"];

NSError *error;

@try{

    if (managedObjectContext != nil) {

        if (![managedObjectContext save:&error]) {

            NSLog(@"Unresolved error %@, %@", error, [error userInfo]);

            NSString * infoString = [NSString stringWithFormat:@"Please check your connection and try again."];

            UIAlertView * infoAlert = [[UIAlertView alloc] initWithTitle:@"Database Connection Error" message:infoString delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil];

            [infoAlert show];

            [infoAlert release];
        } 
    }

}@catch (NSException *exception) {

    NSLog(@"inside exception");
}

получить,

    NSManagedObjectContext *context = [self managedObjectContext];

    NSFetchRequest * fetchRequest = [[NSFetchRequest alloc] init];

    NSEntityDescription *entity1 = [NSEntityDescription entityForName:@"Event" inManagedObjectContext:context];

    [fetchRequest setEntity:entity1];

    NSError *error;

    NSArray * array = [self.managedObjectContext executeFetchRequest:fetchRequest error:&error];

    if (array == nil) {

        NSLog(@"Testing: No results found");

    }else {

        NSLog(@"Testing: %d Results found.", [array count]);
    }

    NSData * dataBytes = [[array objectAtIndex:0] data];

    image = [UIImage imageWithData:dataBytes];

    [fetchRequest release]; 


}

@catch (NSException *exception) {

    NSLog(@"inside exception");
}

Error:
   Testing: 3 Results found.
   2010-07-28 23:27:51.343 IMG_REF[11657:207] -[Event data]: unrecognized selector sent       to  instance 0x5e22ce0
   2010-07-28 23:27:51.344 IMG_REF[11657:207] *** Terminating app due to uncaught   exception 'NSInvalidArgumentException', reason: '-[Event data]: unrecognized selector sent  to instance 0x5e22ce0'
  *** Call stack at first throw:
  (
0   CoreFoundation                      0x02566919 __exceptionPreprocess + 185
1   libobjc.A.dylib                     0x026b45de objc_exception_throw + 47
2   CoreFoundation                      0x0256842b -[NSObject(NSObject) doesNotRecognizeSelector:] + 187
3   CoreFoundation                      0x024d8116 ___forwarding___ + 966
4   CoreFoundation                      0x024d7cd2 _CF_forwarding_prep_0 + 50
5   IMG_REF                             0x00003b06 -[IMG_REFViewController showAction] + 353
6   UIKit                               0x002bae14 -[UIApplication sendAction:to:from:forEvent:] + 119
7   UIKit                               0x004c214b -[UIBarButtonItem(UIInternal) _sendAction:withEvent:] + 156
8   UIKit                               0x002bae14 -[UIApplication sendAction:to:from:forEvent:] + 119
9   UIKit                               0x003446c8 -[UIControl sendAction:to:forEvent:] + 67
10  UIKit                               0x00346b4a -[UIControl(Internal) _sendActionsForEvents:withEvent:] + 527
11  UIKit                               0x003456f7 -[UIControl touchesEnded:withEvent:] + 458
12  UIKit                               0x002de2ff -[UIWindow _sendTouchesForEvent:] + 567
13  UIKit                               0x002c01ec -[UIApplication sendEvent:] + 447
14  UIKit                               0x002c4ac4 _UIApplicationHandleEvent + 7495
15  GraphicsServices                    0x02dccafa PurpleEventCallback + 1578
16  CoreFoundation                      0x02547dc4 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__ + 52
17  CoreFoundation                      0x024a8737 __CFRunLoopDoSource1 + 215
18  CoreFoundation                      0x024a59c3 __CFRunLoopRun + 979
19  CoreFoundation                      0x024a5280 CFRunLoopRunSpecific + 208
20  CoreFoundation                      0x024a51a1 CFRunLoopRunInMode + 97
21  GraphicsServices                    0x02dcb2c8 GSEventRunModal + 217
22  GraphicsServices                    0x02dcb38d GSEventRun + 115
23  UIKit                               0x002c8b58 UIApplicationMain + 1160
24  IMG_REF                             0x00002aac main + 102
25  IMG_REF                             0x00002a3d start + 53
 )
 terminate called after throwing an instance of 'NSException'

Примечание. Вышеупомянутая ошибка возникает при выполнении NSData * dataBytes = [[array objectAtIndex: 0] data]; линия. http://www.freeimagehosting.net/uploads/7c286931cc.png

Я потратил на это много времени. Пожалуйста, помогите мне!


person Sivanathan    schedule 28.07.2010    source источник
comment
Добавьте код, относящийся к тому, как вы помещаете изображение в NSData и как вы его получаете. Непонятные сообщения об ошибках мало помогают   -  person iwasrobbed    schedule 28.07.2010
comment
@IWasRobbed благодарит вас за ответ, и я вставил свой код. пожалуйста, выясни, что я сделал не так.   -  person Sivanathan    schedule 28.07.2010


Ответы (5)


Когда вы извлекаете изображение, вы выполняете запрос на выборку и сохраняете результаты в переменной array, что означает, что array содержит NSArray объектов Event. Позже вы назначаете:

dataBytes = [array objectAtIndex:0];

Это означает, что dataBytes, который вы объявили как NSData, теперь фактически является экземпляром Event. Затем, когда вы переходите к инициализации изображения, часть реализации imageWithData: вызывает length то, что ожидает быть вашим объектом NSData, но на самом деле это объект события, отсюда и сообщение об ошибке.

Вы должны настроить свой код так, чтобы он читал:

dataBytes = [[array objectAtIndex:0] imgPng];

Таким образом, вы получаете первый объект Event из массива, а затем извлекаете его свойство imgPng (экземпляр NSData, что вам и нужно).

В качестве примечания, ваше объявление dataBytes с использованием _10 _-_ 11_ в строке выше может быть лишним, поскольку вы сразу же после этого изменяете dataBytes на данные из вашего события.

person Tim    schedule 28.07.2010
comment
В точности ошибка? Можете ли вы отредактировать свой вопрос выше и скопировать / вставить в него ошибку после обновления? Спасибо. - person Tim; 28.07.2010
comment
@Sivanathan - обратите внимание, что это немного другая ошибка: на этот раз объект Event получает нераспознанный селектор data, а не length. По крайней мере, это означает, что мы на правильном пути. Можете ли вы опубликовать код для своего класса Event (он должен был быть сгенерирован Core Data) или снимок экрана вашей модели Core Data? В частности, я ищу имя получателя для свойства data объекта Event. - person Tim; 28.07.2010
comment
@Tim - я прикрепил снимок экрана моей модели данных и указал мне, если я сделал что-то не так - person Sivanathan; 29.07.2010
comment
@Sivanathan - хорошо, это была моя ошибка. Вместо свойства data используйте свойство imgPng из вашей модели. (Меня захватили все средства доступа к данным в NSData, и я не подумал посмотреть на ваш setValue:forKey: вызов в вашем первом блоке кода.) Я отредактировал свой ответ, чтобы отразить это. - person Tim; 29.07.2010
comment
@ Тим, я тебе очень благодарен. я изменил imgPng, и он работает нормально - person Sivanathan; 29.07.2010

Не уверен, что вы уже исправили это, но я могу сохранять / извлекать UIImage объекты в Core Data следующим образом:

Сохранить:

NSData *imageData = UIImagePNGRepresentation(yourUIImage);
[newManagedObject setValue:imageData forKey:@"image"];

и загрузить:

NSManagedObject *selectedObject = [[self fetchedResultsController] objectAtIndexPath:indexPath];
UIImage *image = [UIImage imageWithData:[selectedObject valueForKey:@"image"]];
[[newCustomer yourImageView] setImage:image];

Надеюсь это поможет. Я использую UITableView с Core Data и извлекаю изображение из базы данных в моем tableView:didSelectRowAtIndexPath: методе.

person Brian Williams    schedule 02.10.2010
comment
Я люблю образцы кодов. Однако было бы неплохо упомянуть, что yourUIImage имеет тип UIImage * - person user4951; 08.10.2012

Вот подходящее решение, которое работает очень хорошо.

1) Хранение UIImage с основными данными:

NSData* coreDataImage = [NSData dataWithData:UIImagePNGRepresentation(delegate.dancePhoto)];

Убедитесь, что «coreDataImage» имеет тип NSData. Вы должны установить тип «Двоичные данные» для «coreDataImage» в вашей модели.

2) Получение UIImage из основных данных:

UIImage* image = [UIImage imageWithData:selectedDance.danceImage];

Вот и все, отлично работает.

person Detra83    schedule 02.02.2011
comment
Извините, я не заметил, что Брайан уже ответил почти таким же решением. - person Detra83; 03.02.2011
comment
Нет необходимости передавать UIImagePNGRepresentation в инициализатор NSData, поскольку он уже возвращает объект NSData. - person Gargoyle; 17.01.2014

Решение, которое я использовал, заключалось в создании категории ниже. Вам просто нужно, чтобы он работал в вашем проекте. Использование этого хранения изображений работает так же, как и при хранении NSData.

UIImage + NSCoding.h

@interface UIImage (UIImage_NSCoding) <NSCoding> 
- (void)encodeWithCoder:(NSCoder *)aCoder;
- (id)initWithCoder:(NSCoder *)aDecoder;
@end

UIImage + NSCoding.m

#import "UIImage+NSCoding.h"

@implementation UIImage (UIImage_NSCoding)

- (void)encodeWithCoder:(NSCoder *)aCoder
{
    NSData *imageData = UIImagePNGRepresentation(self);
    [aCoder encodeDataObject:imageData];
}

- (id)initWithCoder:(NSCoder *)aDecoder
{
    [self autorelease];
    NSData* imageData = [aDecoder decodeDataObject];
    self = [[UIImage alloc] initWithData:imageData];
    return self;
}
@end
person rp90    schedule 01.05.2011
comment
да, это самый простой способ, потому что если класс соответствует протоколу NSCoding, то можно использовать NSKeyedUnarchiveFromDataTransformerName (стандарт для основных данных). - person CarlJ; 16.04.2012
comment
Я смущен. Нигде не используется NSKeyedUnarchiveFromDataTransformerName. - person user4951; 08.10.2012
comment
На самом деле UIImage уже соответствует NSCoding без необходимости добавления какого-либо кода. Таким образом, его можно использовать как атрибут Transformable. см. Сохранение UIImage в CoreData без написания кода - person Yonat; 12.01.2015

В этом образце кода есть пример хранения UIImage в основных данных: https://developer.apple.com/library/ios/#samplecode/PhotoLocations/Introduction/Intro.html

person Michal Gumny    schedule 28.01.2013