NSLog和核心数据

时间:2009-11-16 11:18:11

标签: objective-c iphone xcode core-data

我有三个类,我正在扩展NSManagedObject(我知道这不是必需的,但我想要属性表示法)。这些课程是问题集,问题和答案。设置我的数据模型,以便它们之间存在多对多:问题集<< - >>问题<< - >>回答。我从服务器加载所有内容并成功保存意味着我查看.db文件,这就是我所期望的,如果我立即NSLog他们看起来很棒的数组问题集,如果我去参加一个测验它很有用。

但是,如果我在任何地方NSLog那个数组,但在我从服务器加载它们之后,它会崩溃我的应用程序。测验仍然运行正常,所以我知道数据在那里并以预期的格式。这是否与Core Data清除空间有关,然后当我只是尝试登录时,我的关系不会“懒得加载”?对不起,我仍然围绕着核心数据。

这个位工作,我从服务器加载,在底部我'loadTrivia'并记录我得到的。问题是,如果在应用程序执行过程中的某个时间后,问题集的NSLog将失败。

- (void)loadQuestionSetFromNetworkWithID:(NSNumber *)p_id andTitle:(NSString *)p_title
{
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:[NSString stringWithFormat:kTriviaQuestionSetURL, [p_id intValue]]]];
[UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
NSData *response = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
NSString *json_string = [[NSString alloc] initWithData:response encoding:NSUTF8StringEncoding];

NSArray *questions = [[[sbjson objectWithString:json_string error:nil] valueForKeyPath:@"Q"] objectAtIndex:0];

NSError *error;

NSFetchRequest *questionsetRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *questionsetEntity = [NSEntityDescription entityForName:@"QuestionSet" inManagedObjectContext:[self managedObjectContext]];
NSPredicate *questionsetPredicate = [NSPredicate predicateWithFormat:@"id = %d", [p_id intValue]];

[questionsetRequest setEntity:questionsetEntity];
[questionsetRequest setPredicate:questionsetPredicate];

QuestionSet *qs = nil;
NSArray *questionSetObjects = [[self managedObjectContext] executeFetchRequest:questionsetRequest error:&error];
if (questionSetObjects == nil){
    // Handle errors
}
if ([questionSetObjects count] > 0)
    qs = [questionSetObjects objectAtIndex:0];
else
    qs = [NSEntityDescription insertNewObjectForEntityForName:@"QuestionSet" inManagedObjectContext:[self managedObjectContext]];

qs.id = p_id;
qs.title = p_title; 

for (int i = 0; i < [questions count]; i++)
{
    NSFetchRequest *questionRequest = [[NSFetchRequest alloc] init];
    NSEntityDescription *questionEntity = [NSEntityDescription entityForName:@"Question" inManagedObjectContext:[self managedObjectContext]];
    NSPredicate *questionPredicate = [NSPredicate predicateWithFormat:@"(id = %d)", [[[questions objectAtIndex:i] objectForKey:@"id"] intValue]];

    [questionRequest setEntity:questionEntity];
    [questionRequest setPredicate:questionPredicate];

    Question *q = nil;
    NSArray *questionObjects = [[self managedObjectContext] executeFetchRequest:questionRequest error:&error];
    if (questionObjects == nil){
        // Handle errors
    }
    if ([questionObjects count] > 0)
        q = [questionObjects objectAtIndex:0];
    else
        q = [NSEntityDescription insertNewObjectForEntityForName:@"Question" inManagedObjectContext:[self managedObjectContext]];

    q.id = [NSNumber numberWithInt:[[[questions objectAtIndex:i] objectForKey:@"id"] intValue]];
    q.question = [[questions objectAtIndex:i] objectForKey:@"text"];
    q.answer = [NSNumber numberWithInt:[[[questions objectAtIndex:i] objectForKey:@"ca"] intValue]];

    for (int j = 0; j < [[[questions objectAtIndex:i] objectForKey:@"A"] count]; j++)
    {
        NSFetchRequest *answerRequest = [[NSFetchRequest alloc] init];
        NSEntityDescription *answerEntity = [NSEntityDescription entityForName:@"Answer" inManagedObjectContext:[self managedObjectContext]];
        NSPredicate *answerPredicate = [NSPredicate predicateWithFormat:@"(id = %d)", [[[[[questions objectAtIndex:i] objectForKey:@"A"] objectAtIndex:j] objectForKey:@"id"] intValue]];

        [answerRequest setEntity:answerEntity];
        [answerRequest setPredicate:answerPredicate];

        Answer *a = nil;
        NSArray *answerObjects = [[self managedObjectContext] executeFetchRequest:answerRequest error:&error];
        if (answerObjects == nil){
            // Handle errors
        }
        if ([answerObjects count] > 0)
            a = [answerObjects objectAtIndex:0];
        else
            a = [NSEntityDescription insertNewObjectForEntityForName:@"Answer" inManagedObjectContext:[self managedObjectContext]];

        a.id = [NSNumber numberWithInt:[[[[[questions objectAtIndex:i] objectForKey:@"A"] objectAtIndex:j] objectForKey:@"id"] intValue]];
        a.answer = [[[[questions objectAtIndex:i] objectForKey:@"A"] objectAtIndex:j] objectForKey:@"text"];

        a.questions = [a.questions setByAddingObject:q];
        q.answers = [q.answers setByAddingObject:a];

        [answerRequest release];
    }

    q.questionsets = [q.questionsets setByAddingObject:qs];
    qs.questions = [qs.questions setByAddingObject:q];

    [questionRequest release];

}

[questionsetRequest release];

[[self managedObjectContext] save:&error];

[json_string release];

[self loadTrivia];
NSLog(@"After Load: %@", self.questionsets);
}

此函数从db中获取所有QuestionSet对象,并将数组存储在ivar中。

- (BOOL)loadTrivia
{
NSError *error;
NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"QuestionSet" inManagedObjectContext:[self managedObjectContext]];
[request setEntity:entity];
self.questionsets = [[self managedObjectContext] executeFetchRequest:request error:&error];
return YES;
}

为了完整起见,这是我的课程中的描述方法

来自QuestionSet.h的

- (NSString *)description
{
return [NSString stringWithFormat:@"\
        \n\tid: %@\
        \n\ttitle: %@\
        \n\tquestions: %@\n",
        self.id, 
        self.title, 
        self.questions];
}
来自Question.h的

- (NSString *)description
{
return [NSString stringWithFormat:@"\
        \n\tid: %@\
        \n\tanswer: %@\
        \n\tquestion: %@\
        \n\tanswers: %@\n", 
        self.id, 
        self.answer, 
        self.question, 
        self.answers];
}
来自Answer.h的

- (NSString *)description
{
return [NSString stringWithFormat:@"\
        \n\tid: %@\
        \n\tanswer: %@\n",
        self.id, 
        self.answer];
}

1 个答案:

答案 0 :(得分:2)

您不应该对描述方法(Link)进行子类化:

  

尽管描述方法不会导致触发错误,但如果实现访问对象的持久属性的自定义描述方法,则会导致触发错误。强烈建议您不要以这种方式覆盖描述。

我在我的应用上测试了你的loadTrivia代码(使用不同的entityName)并且工作正常。 您是否看过NSError(您应该使用= nil初始化它):

NSLog(@"Unresolved error %@, %@", error, [error userInfo]);

此外,您应该在- (BOOL)loadTrivia执行后释放NSFetchRequest。