CoreData:从 Context/Store NSData -> NSArray 解码数据时出错



我是iOS开发领域的新手,现在正尝试将现有应用程序从iOS4更新到iOS 6.1。

从商店获取数据以在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);
}

尝试将数据设置/写入上下文

-(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

型号消息属性:类别类型:可转换名称:NewsTransformer

关系芯片一个到多个类别Des。新闻分类反向新闻

分类Att.catId字符串收件人姓名Interger16

我的问题:1.将数据写入上下文-OK2.当我试图从上下文(NSData->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'

知道我做错了什么吗??

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

if (self = [super init]) {

不能使用init创建托管对象。必须使用指定的初始值设定项initWithEntity:insertIntoManagedObjectContext:。也可以使用NSEntityDescription的方法insertNewObjectForEntityForName:inManagedObjectContext:。但是使用init是正确的,这样做会导致Failed to call designated initializer错误。

这意味着您的initWithCoder需要能够找到托管对象上下文。你如何做到这一点取决于你的应用程序的结构以及你在哪里创建上下文。如果你的应用程序代理有一个上下文对象,而这正是你想要使用的对象,你可以从那里查找它。如果是其他上下文,你必须从其他地方获得它。您有两个版本的initWithCoder,它们都有这个问题。

第二个错误是第一个错误的副作用。在initWithCoder中,您可以执行以下操作:

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

但由于[super init]不起作用,你得到了一个不知道catId是什么的伪对象。然后你试图设置catId,但它失败了。修复第一个错误,第二个错误将消失。

最新更新