CoreData:来自Context / Store NSData的解码数据出错 - > NSArray的

时间:2013-11-20 15:43:18

标签: core-data ios6

我是iOS-Development领域的新手,现在尝试从iOS4将现有应用更新到iOS 6.1。

  
    
      

从Store中获取数据以显示在NewsPageView:UIViewController

中     
  
NewsPageView.m

#import "NewsPageView.h"

@interface NewsPageView ()

@end

@implementation NewsPageView

@synthesize newsDetailsView,
            newsTableView,
            newsHeaderText
;


- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view.

    /*
     * Get managedObjectContext and List of News over AppDelegate
     */
    AppDelegate* appDelegate = [UIApplication sharedApplication].delegate;

    //Setting self.managedObjectContext
    self.managedObjectContext = appDelegate.managedObjectContext;

    // Fetching Records from the data base to show in the table
    self.listOfNews = [[appDelegate getDataFromStore:self]copy];

    //
    NSLog(@"Data from Store in NewsPageView: %@",self.listOfNews.description);
}
  
    
      

尝试将数据设置/写入Context

    
  
-(void) setDataToStore
{

    NSLog(@"Trying to write News in Store");

    News *newNews = [NSEntityDescription insertNewObjectForEntityForName:@"News" inManagedObjectContext:self.managedObjectContext];
    newNews.newsId = [[NSNumber alloc]initWithInt:508];
    newNews.title = @"Some Title";
    newNews.content = @"Some content";
    newNews.detailsUrl = @"www.someURL.de";
    newNews.date = [[NSDate alloc]init];
    newNews.dateTs = [[NSNumber alloc]initWithInt:138114787];
    newNews.primaryCat = [[NSNumber alloc]initWithInt:0];

    //make Categorien...
    NewsCategorien *cat1 = [NSEntityDescription insertNewObjectForEntityForName:@"NewsCategorien" inManagedObjectContext:self.managedObjectContext];
    cat1.catId = [[NSNumber alloc]initWithInt:1];
    cat1.name = @"Windows";
    cat1.news = newNews;

    NewsCategorien *cat2 = [NSEntityDescription insertNewObjectForEntityForName:@"NewsCategorien" inManagedObjectContext:self.managedObjectContext];
    cat2.catId = [[NSNumber alloc]initWithInt:2];
    cat2.name = @"Linux";
    cat2.news = newNews;

    NewsCategorien *cat3 = [NSEntityDescription insertNewObjectForEntityForName:@"NewsCategorien" inManagedObjectContext:self.managedObjectContext];
    cat3.catId = [[NSNumber alloc]initWithInt:3];
    cat3.name = @"Apple";
    cat3.news = newNews;

    NewsCategorien *cat5 = [NSEntityDescription insertNewObjectForEntityForName:@"NewsCategorien" inManagedObjectContext:self.managedObjectContext];
    cat5.catId = [[NSNumber alloc]initWithInt:5];
    cat5.name = @"Smartphone";
    cat5.news = newNews;

    newNews.isNews = [NSNumber numberWithBool:YES];

    NSArray *catListe = [NSArray arrayWithObjects:cat1,cat2,cat3,cat5, nil];


//    //saving cat by converting Cat. objects
//    newNews.categories = catListe;

    NSError *error;
    if (![self.managedObjectContext save:&error]) {
        NSLog(@"Whoops, couldn't save: %@", [error localizedDescription]);
    }

    NSLog(@"Saving ok!");
}
  
    
      

尝试从上下文中获取数据

    
  
- (NSArray *)getDataFromStore:(id)sender
{
    // initializing NSFetchRequest
    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];

    NSArray *fetchedData;

    //get Data für NewsTable View
    if([sender isKindOfClass:[NewsPageView class]]){

        //Setting Entity to be Queried
        fetchRequest.entity = [NSEntityDescription entityForName:@"News" inManagedObjectContext:self.managedObjectContext];
        NSError* error;

//Point of Error by debugging!!!
        //return list of News
        fetchedData = [self.managedObjectContext executeFetchRequest:fetchRequest error:&error];

    }

    //print fetched Data
    for (News *news in fetchedData) {
        NSLog(@"News:%@", news.description);
    }

    // Returning Fetched News
    return fetchedData;
}
  
    
      

    
  
News.h

#import <Foundation/Foundation.h>
#import <CoreData/CoreData.h>

@class NewsCategorien;

@interface News : NSManagedObject <NSCoding>

@property (nonatomic, retain) id categories;
@property (nonatomic, retain) NSString * content;
@property (nonatomic, retain) NSDate * date;
@property (nonatomic, retain) NSNumber * dateTs;
@property (nonatomic, retain) NSString * detailsUrl;
@property (nonatomic, retain) NSNumber * isNews;
@property (nonatomic, retain) NSNumber * newsId;
@property (nonatomic, retain) NSNumber * primaryCat;
@property (nonatomic, retain) NSString * title;
@property (nonatomic, retain) NSSet *categorie;


//have to be implement...
//to work with NSKeyedArchiver by serialising Objects
- (void)encodeWithCoder:(NSCoder *)aCoder;

//to work with NSKeyedUnarchiver by deserialising Objects
- (id)initWithCoder:(NSCoder *)aDecoder;

@end

@interface News (CoreDataGeneratedAccessors)

- (void)addCategorieObject:(NewsCategorien *)value;
- (void)removeCategorieObject:(NewsCategorien *)value;
- (void)addCategorie:(NSSet *)values;
- (void)removeCategorie:(NSSet *)values;

@end

/*
 * News Transformer NSArray -> NSData and reverse
 * Model: News should have Attribut type of Transformable and have name NewsTrasformer
 */

@interface NewsTransformer : NSValueTransformer

@end

News.m
#import "News.h"
#import "NewsCategorien.h"


@implementation News

@dynamic categories;
@dynamic content;
@dynamic date;
@dynamic dateTs;
@dynamic detailsUrl;
@dynamic isNews;
@dynamic newsId;
@dynamic primaryCat;
@dynamic title;
@dynamic categorie;

//tell the archiver how to transform the serialized representation into a new object -> deserialize Objects!
- (id)initWithCoder:(NSCoder *)decoder {

    if (self = [super init]) {
        self.categories = [decoder decodeObjectForKey:@"categories"];
        self.content = [decoder decodeObjectForKey:@"content"];
        self.date = [decoder decodeObjectForKey:@"date"];
        self.dateTs = [decoder decodeObjectForKey:@"dateTs"];
        self.detailsUrl = [decoder decodeObjectForKey:@"detailsUrl"];
        self.isNews = [decoder decodeObjectForKey:@"isNews"];
        self.newsId = [decoder decodeObjectForKey:@"newsId"];
        self.primaryCat = [decoder decodeObjectForKey:@"primaryCat"];
        self.title = [decoder decodeObjectForKey:@"title"];
        self.categorie = [decoder decodeObjectForKey:@"categorie"];
    }

    NSLog(@"<<<< ---- Deserialize Object News (Init With Code) --->");

    return self;
}

//tell the archiver how to serialize your object into bytes -> serialize Objects!
- (void)encodeWithCoder:(NSCoder *)encoder {

    [encoder encodeObject:self.categories forKey:@"categories"];
    [encoder encodeObject:self.content forKey:@"content"];
    [encoder encodeObject:self.date forKey:@"date"];
    [encoder encodeObject:self.dateTs forKey:@"dateTs"];
    [encoder encodeObject:self.detailsUrl forKey:@"detailsUrl"];
    [encoder encodeObject:self.isNews forKey:@"isNews"];
    [encoder encodeObject:self.newsId forKey:@"newsId"];
    [encoder encodeObject:self.primaryCat forKey:@"primaryCat"];
    [encoder encodeObject:self.title forKey:@"title"];
    [encoder encodeObject:self.categorie forKey:@"categorie"];

    NSLog(@"<<<< ---- Serialize Object News (encode With Coder) --->");
}

@end

//
@implementation NewsTransformer

//Return the Class for Forwarding Transformation
+ (Class)transformedValueClass
{
    return [NSArray class];
}

+ (BOOL)allowsReverseTransformation
{
    return YES;
}

// converts the NSArray into NSData using NSKeyedArchiver
- (id)transformedValue:(id)value
{
    NSLog(@"Transformer: NSArray -> NSData");
    return [NSKeyedArchiver archivedDataWithRootObject:value];
}

// by default raises an exception if +allowsReverseTransformation returns NO and otherwise invokes transformedValue:
//converts NSData to an NSArray using NSKeyedUnarchiver
- (id)reverseTransformedValue:(id)value
{
    NSLog(@"Transformer: NSData -> NSArray");
    return [NSKeyedUnarchiver unarchiveObjectWithData:value];
}

@end

NewsCategorien.h

#import <Foundation/Foundation.h>
#import <CoreData/CoreData.h>

@class News;

@interface NewsCategorien : NSManagedObject <NSCoding>

@property (nonatomic, retain) NSNumber * catId;
@property (nonatomic, retain) NSString * name;
@property (nonatomic, retain) News *news;

//for serializing of objects have to be implement...
- (void)encodeWithCoder:(NSCoder *)aCoder;

//for serializing of objects have to be implement...
- (id)initWithCoder:(NSCoder *)aDecoder;

@end


NewsCategorien.m

#import "NewsCategorien.h"
#import "News.h"


@implementation NewsCategorien

@dynamic catId;
@dynamic name;
@dynamic news;

- (id)initWithCoder:(NSCoder *)decoder {

    if (self = [super init]) {
        self.catId = [decoder decodeObjectForKey:@"catId"];
        self.name = [decoder decodeObjectForKey:@"name"];
        self.news = [decoder decodeObjectForKey:@"news"];
    }

    NSLog(@"<<<< ---- Deserialize Object Categorie ---> : %@",self.description);

    return self;
}

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

    [encoder encodeObject:self.catId forKey:@"catId"];
    [encoder encodeObject:self.name forKey:@"name"];
    [encoder encodeObject:self.news forKey:@"news"];

    NSLog(@"<<<< ---- Serialize Object Categorie ---> %@",self.description);
}

@end
  
    
      

模型       新闻       属性:categorien类型:可转换名称:NewsTransformer

    
  

Relationchip one-to-more 分类Des。 NewsCategorien反向新闻

Categorien ATT。 catId String ATT。名字Interger16

  
    
      

我的问题:       1.将数据写入上下文 - 好的       2.当我试图从上下文中获取数据时(NSData-&gt; NSArray)我得到以下错误:

             

错误

    
  
CoreData: error: Failed to call designated initializer on NSManagedObject class 'NewsCategorien' 
2013-11-20 16:03:19.204 securityNews[19458:c07] -[NewsCategorien setCatId:]: unrecognized selector sent to instance 0x8173740
2013-11-20 16:03:19.205 securityNews[19458:c07] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[NewsCategorien setCatId:]: unrecognized selector sent to instance 0x8173740'

知道我做错了什么?

1 个答案:

答案 0 :(得分:0)

第一个错误几乎肯定是由于您initWithCoder:的实施,特别是这一行:

if (self = [super init]) {

您无法使用init创建托管对象。您必须使用指定的初始化程序initWithEntity:insertIntoManagedObjectContext:。或者您可以使用NSEntityDescription的方法insertNewObjectForEntityForName:inManagedObjectContext:。但是使用init是正确的,这样做会导致Failed to call designated initializer错误。

这意味着您的initWithCoder需要能够找到托管对象上下文。如何执行此操作取决于您的应用程序的结构以及创建上下文的位置。如果你的app委托有一个上下文对象,那就是你想要使用的对象,你可以从那里查找它。如果是其他一些背景,你必须从其他地方获得它。你有几个initWithCoder版本,他们都有这个问题。

第二个错误是第一个错误的副作用。在initWithCoder中执行此操作:

if (self = [super init]) {
    self.catId = [decoder decodeObjectForKey:@"catId"];
    ....

但是由于[super init]不起作用,你会找回一个不知道catId是什么的虚假对象。然后你尝试设置catId并且它失败了。修复第一个错误,第二个错误将消失。