2010-03-01 291 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