【问题标题】:NSLog and Core DataNSLog 和核心数据
【发布时间】:2023-03-12 17:01:02
【问题描述】:

我有三个要扩展 NSManagedObject 的类(我知道这不是必需的,但我想要属性符号)。论文类是 QuestionSet、Question 和 Answer。我的数据模型已设置好,因此它们之间存在多对多,如下所示: QuestionSet > Question > Answer。我从服务器加载所有内容并成功保存,这意味着我查看 .db 文件,这就是我所期望的,如果我立即 NSLog 数组问题集,它们看起来很棒,如果我去参加测验,效果很好。

但是,如果我在从服务器加载它们之后的任何地方 NSLog 该数组,它会使我的应用程序崩溃。测验仍然运行良好,所以我知道数据在那里并且是预期的格式。这是否与核心数据清理空间有关,然后我的关系在我试图记录它们时不会“延迟加载”?抱歉,我还在纠结核心数据。

这一点有效,我从服务器加载,在底部我“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);
}

此函数从数据库中获取所有 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];
}

【问题讨论】:

    标签: objective-c iphone xcode core-data


    【解决方案1】:

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

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

    我在我的应用程序上测试了您的 loadTrivia 代码(使用不同的 entityName),它运行良好。 你看过NSError吗(你应该用=nil初始化它):

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

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

    【讨论】:

    • 我会说那是相当铁板的。
    • 抱歉更多信息。 loadQuestionSetFromNetworkWithID:andTitle: 和 loadTrivia: 都为我工作,但我把它放在那里以防有人认为我的错误在那里。谢谢您的帮助!罗伯
    • 很高兴我能帮上忙。出了什么问题?
    • 唯一真正导致错误的是使用自定义描述方法对 NSManagedObject 的 NSLog 调用,除了应用程序完全按照我的预期工作。看到您发布的链接后,我意识到我无法拥有自己的链接。所以真的很简单。 NSManagedObject 提供的描述对我来说似乎已经足够好了。
    猜你喜欢
    • 2011-03-07
    • 2011-01-11
    • 1970-01-01
    • 2010-12-04
    • 2014-09-18
    • 2013-01-24
    • 2011-12-04
    • 2011-10-22
    • 1970-01-01
    相关资源
    最近更新 更多