2010-03-01 96 views
2

我是Objective C新手,想知道是否有人可以帮助我。如何将NSManagedObjects的NSArray转换为NSData

我正在使用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),但我即使在阅读documentation之后,我也不确定该怎么做,我的尝试如下。我不知道我是否沿着这条线走,因为得到一个警告,说明“NSManagedObject”可能不会响应'-encodeWithCoder'“

我真的很感激,如果有人能指点我正确的方向!!

由于

ç

这里是我的GamerProfile(CoreData NSManagedObject对象)与我在添加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

NSManagedObject和NSCoding真的不玩好起来。考虑this answer to a similar question的背景和可能的解决方案。

+0

非常感谢Ole! – carok 2010-03-02 08:51:52

+0

我同意@Ole - 但有一种方法可以使其工作,如果需要,我在他提供的链接上添加了对问题的回复。基本上,'initWithEncoder:'必须调用'[super initWithEntity:insertIntoManagedObjectContext:]' - 要做到这一点,你需要一个全局变量来获取你正在解析的上下文 – bshirley 2011-07-07 03:47:26

4

我得到了这个工作。就是这样。

首先创建一个NSValueTransformer像这样:

ArrayToDataTransformer.h

@interface ArrayToDataTransformer : NSValueTransformer { 

} 

@end 

ArrayToDataTransformer.m

进口 “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 

阵列。米

#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"]; 

如果使用一到-many,并且事物的名称如上所示,您将返回一个NSSet。

核心数据应该将数组作为Blob存储在数据库中,并且可以快速写入大型数组,比如说一个包含3,500个对象的数组需要的时间少于1秒。性能与UIImage如何使用几乎相同的概念进行存储和检索相当。我认为检索速度更快。 另一种方法是将数组的每个值分别写入核心数据。为此,您需要创建适当的NSManageObject,但要注意每个数组值需要保存3500次,对于3500个项目,这需要20到30秒。 因此,上面的方法非常适合一次性将大数组写入CoreData,并且一次性检索它们。 在这个花了几个小时,正要放弃,然后我看到了光!

+0

几年前,仍然设法帮助我! – 2014-08-04 00:01:14