Как преобразовать NSArray NSManagedObjects в NSData - PullRequest
2 голосов
/ 01 марта 2010

Я новичок в Objective C и задавался вопросом, может ли кто-нибудь мне помочь.

Я использую базовые данные с базой данных sqlite для хранения простых объектов профиля, которые имеют имя и атрибут оценки (оба из которых имеют тип NSString).

Что я хочу сделать, это получить профили и сохранить их в объекте NSData, см. Мой код ниже:

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

            NSEntityDescription *entity = [NSEntityDescription entityForName:@"GamerProfile" inManagedObjectContext:managedObjectContext];
            [fetchRequest setEntity:entity];

            NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"Name" ascending:YES];
            NSArray *sortDecriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
            [fetchRequest setSortDescriptors:sortDecriptors];

            [sortDescriptor release];
            [sortDecriptors release];           

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

            NSData *data = [NSKeyedArchiver archivedDataWithRootObject:items];

            [self SendData:data];
            [fetchRequest release];

Когда я запускаю код, я получаю сообщение об ошибке «Завершение приложения из-за необработанного исключения« NSInvalidArgumentException », причина: '*** - [GamerProfile encodeWithCoder:]: нераспознанный селектор, отправленный экземпляру 0x3f4b530'"

Я предполагаю, что мне нужно добавить encodeWithCoderClass к моему базовому объекту NSManagedObject данных (GamerProfile), но я не уверен, как это сделать, даже после прочтения документации , моя попытка сделать это ниже. Я не уверен, что я иду по правильному пути с этим, поскольку получаю предупреждение о том, что «NSManagedObject» может не отвечать на «-encodeWithCoder»

Я бы очень, очень признателен, если бы кто-то мог указать мне правильное направление !!

Спасибо

C

Вот код для моего GamerProfile (CoreData NSManagedObject Object) с моей попыткой добавить метод encodeWithCoder ...

Заголовочный файл

#import <CoreData/CoreData.h>


@interface GamerProfile :  NSManagedObject <NSCoding>
{
}

@property (nonatomic, retain) NSString * GamerScore;
@property (nonatomic, retain) NSString * Name;

- (void)encodeWithCoder:(NSCoder *)coder;


@end

Кодовый файл

#import "GamerProfile.h"


@implementation GamerProfile 

@dynamic GamerScore;
@dynamic Name;

- (void)encodeWithCoder:(NSCoder *)coder {

    [super encodeWithCoder:coder];

    [coder encodeObject:GamerScore forKey:@"GamerScore"];
    [coder encodeObject:Name forKey:@"Name"];



}

Ответы [ 2 ]

4 голосов
/ 04 апреля 2010

Я получил это на работу. Вот как.

Сначала создайте NSValueTransformer примерно так:

ArrayToDataTransformer.h

@interface ArrayToDataTransformer : NSValueTransformer {

}

@end

ArrayToDataTransformer.m

import "ArrayToDataTransformer.h"

@implementation ArrayToDataTransformer

+ (BOOL)allowsReverseTransformation {
    return YES;
}

+ (Class)transformedValueClass {
    return [NSData class];
}

- (id)transformedValue:(id)value {
    //Take an NSArray archive to NSData
    NSData *data = [NSKeyedArchiver archivedDataWithRootObject:value];
    return data;
}

- (id)reverseTransformedValue:(id)value {
    //Take NSData unarchive to NSArray 
    NSArray *array = (NSArray*)[NSKeyedUnarchiver unarchiveObjectWithData:value];
    return array;
}

@end

Выше интерфейс вашего NSManagedObject, теперь создайте тот, который его использует, например:

Array.h

#import <CoreData/CoreData.h>

@class Arrays;

@interface Array :  NSManagedObject  
{
}

@property (nonatomic, retain) id myArray;
@property (nonatomic, retain) Arrays * arrayOfArrays;

@end

Array.m

#import "Array.h"

#import "Arrays.h"

@implementation Array 

@dynamic myArray;
@dynamic arrayOfArrays;

@end

В xcdatamodel для массива необходимо, чтобы атрибуты myArray были установлены как Необязательные (обычно всегда отмечены), а Тип: Преобразуемый и Имя преобразователя значения: ArrayToDataTransformer

Теперь вы можете использовать его;

NSMutableArray* positionArray;
positionArray = [[NSMutableArray alloc] arrayWithCapacity:[myArray count]];

for(NSArray *pos in myArray) {
        [positionArray addObject:[NSString stringWithFormat:@"%@",pos]];
}

NSLog(@"ArrayCtrl : positionArray cnt = %d",[positionArray count]);


    //Now add the positionArray to CoreData using the setValue & myArray Key
    Array *array = (Array*)[NSEntityDescription insertNewObjectForEntityForName:@"Array" inManagedObjectContext:self.managedObjectContext];
    [array setValue:positionArray forKey:@"myArray"];
    [myArrays setMyArrays:array];
    [self saveAction:array];
    [positionArray release];

Чтобы извлечь данные из CoreData:

используя отношение один к одному, таким образом, myArrays указывает только на один элемент массива

NSArray *positionArray = [myArrays.array valueForKey:@"myArray"];

Если вы используете один-ко-многим, а вещи названы, как указано выше, вы получите NSSet.

Базовые данные должны хранить массив в виде большого двоичного объекта в базе данных, и большой массив можно записать очень быстро, например, для одного из 3500 объектов требуется меньше секунды. Производительность сопоставима с тем, как UIImage хранится и извлекается, используя почти те же концепции. Поиск, я думаю, еще быстрее. Альтернатива - записать каждое значение массива индивидуально в базовые данные. Для этого вам нужно создать соответствующий NSManageObject, но учтите, что вам придется экономить 3500 раз для каждого значения массива, а для 3500 элементов это займет от 20 до 30 секунд. Таким образом, описанный выше метод отлично подходит для записи больших массивов в CoreData за один снимок и извлечения их также за один снимок. Потратил на это несколько часов, собирался сдаться, а потом я увидел свет!

2 голосов
/ 01 марта 2010

NSManagedObject и NSCoding действительно не очень хорошо сочетаются друг с другом.Рассмотрим этот ответ на аналогичный вопрос для фона и возможного решения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...