Запазване и извличане на UIImage на CoreData

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

случай 1: При опит за показване като низ от DB.

 <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 от обекти на събитие. След това по-късно присвоявате:

dataBytes = [array objectAtIndex:0];

Това означава, че dataBytes, което сте декларирали като NSData, сега всъщност е екземпляр на Event. След това, когато отидете да инициализирате изображението, част от изпълнението на imageWithData: извиква length на това, което очаква да бъде вашият NSData обект, но всъщност е обект на събитие, оттук и съобщението за грешка.

Трябва да коригирате кода си, за да чете:

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

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

Като странична бележка, вашата декларация на dataBytes с помощта на alloc-init на реда по-горе може да е ненужна, тъй като веднага след това променяте 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
@Tim наистина ти благодаря. промених 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 с основни данни и изтеглям изображението от базата данни в моя 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 в Core Data: https://developer.apple.com/library/ios/#samplecode/PhotoLocations/Introduction/Intro.html

person Michal Gumny    schedule 28.01.2013