难以调试 iPhone Core Data 错误

Posted

技术标签:

【中文标题】难以调试 iPhone Core Data 错误【英文标题】:Having difficulty debugging a iPhone Core Data bug 【发布时间】:2010-02-20 23:11:32 【问题描述】:

我希望有人可以帮助我调试一个令人难以置信的令人沮丧的 Core Data 崩溃。我最初将数据加载到两个实体(代表“演讲者”和“标题”)中,然后为“会话”加载第三个实体,并尝试将关系设置为“演讲者”和“标题”。 (从会话到演讲者和标题是一对一的。从演讲者/标题回到会话是一对多的)。我使用整数键来设置每个关系。

由于给定的演讲者和标题可以指向多个会话,我编写了一个函数来搜索适当的托管对象并返回该对象。然后我为关系设置它。

这对于说话者关系来说效果很好,但对于 SECOND 标题来说却始终如一且可怕地崩溃。我已经以不同的方式重写了几次代码,但我总是遇到同样的问题。无论什么标题排在第二位,问题都存在。所以我必须做一些根本上错误的事情,但是按照更多 iPhone 3 开发中的核心数据章节,我没有任何反应。我希望有人可能会看到我缺少的东西(并且已经好几天了)。 (最后一点:无论我将 managedObjectContext 保存在 for 循环内还是外部都会发生崩溃。总是在第二个会话中)。我对任何可以帮助我的人表示无尽的感谢和第一个出生的孩子。

以下是保存会话实体的相关代码:

    for (NSDictionary *session in self.sessions)
        NSManagedObject *newSession = [NSEntityDescription insertNewObjectForEntityForName:[sessionEntity name] inManagedObjectContext:self.managedObjectContext];
        [newSession setValue:[session valueForKey:@"ID"] forKey:@"id"];
        [newSession setValue:[session valueForKey:@"notes"] forKey:@"notes"];
        [newSession setValue:[session valueForKey:@"length"] forKey:@"length"];

        //get the speaker value;
        [newSession setValue:[self setupSpeaker:[session valueForKey:@"speaker"]] forKey:@"speaker"];
        NSLog(@"now doing title");
        //now get the title value;
        [newSession setValue:[self setupTitle:[session valueForKey:@"title"]] forKey:@"title"];
        NSLog(@"I got back this title:%@", [newSession valueForKey:@"title"]);

           

        if (![self.managedObjectContext save:&error]) 
            NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
            abort();

这是为关系找到合适的说话者和标题实体的代码(我意识到这很多余)

-(NSManagedObject *) setupSpeaker:(NSNumber *)id 
    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
    NSEntityDescription *entity = [NSEntityDescription entityForName:@"Speaker" inManagedObjectContext:self.managedObjectContext];
    [fetchRequest setEntity:entity];

    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"id==%@",id];
    [fetchRequest setPredicate:predicate];

    NSError *error;
    NSArray *items=[self.managedObjectContext executeFetchRequest:fetchRequest error:&error];
    [fetchRequest release];

    if ([items count]>=1)
        return [items objectAtIndex:0];
    else
        return 0;
    

-(NSManagedObject *) setupTitle:(NSNumber *)id 
    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
    NSEntityDescription *entity = [NSEntityDescription entityForName:@"Title" inManagedObjectContext:self.managedObjectContext];
    [fetchRequest setEntity:entity];
    NSLog(@"now looking for: %@", id);
    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"id==%@",id];
    [fetchRequest setPredicate:predicate];

    NSError *error;
    NSArray *items=[self.managedObjectContext executeFetchRequest:fetchRequest error:&error];
    [fetchRequest release];

    if ([items count]>=1)
        NSLog(@"found %@", id);
        return [items objectAtIndex:0];
    else
        return 0;
    

最后是崩溃时的日志:

2010-02-20 16:48:17.134 iconf[1438:207] now looking for: 1
    2010-02-20 16:48:17.136 iconf[1438:207] found 1
    2010-02-20 16:48:17.156 iconf[1438:207] I got back this title:<NSManagedObject: 0x3b11a10> (entity: Title; id: 0x3d4a3c0 <x-coredata://B76F62BD-AC82-4335-9013-7529C2471F9C/Title/p6> ; data: 
        id = 1;
        session =     (
            0x3d51640 <x-coredata:///Session/t2765697F-14C9-4282-A067-10A2413732B834>
        );
        title = "Bill Gates Speaks";
    )
    2010-02-20 16:48:17.158 iconf[1438:207] now doing title
    2010-02-20 16:48:17.158 iconf[1438:207] now looking for: 2
    2010-02-20 16:48:17.159 iconf[1438:207] found 2
    2010-02-20 16:48:17.161 iconf[1438:207] I got back this title:<NSManagedObject: 0x3b16fd0> (entity: Title; id: 0x3d4d7a0 <x-coredata://B76F62BD-AC82-4335-9013-7529C2471F9C/Title/p12> ; data: 
        id = 2;
        session =     (
            0x3b1b320 <x-coredata:///Session/t2765697F-14C9-4282-A067-10A2413732B835>
        );
        title = "Lecture on Frogs";
    )
    2010-02-20 16:48:17.161 iconf[1438:207] *** -[NSManagedObject compare:]: unrecognized selector sent to instance 0x3b11a10
    2010-02-20 16:48:17.162 iconf[1438:207] Serious application error.  Exception was caught during Core Data change processing: *** -[NSManagedObject compare:]: unrecognized selector sent to instance 0x3b11a10 with userInfo (null)
    2010-02-20 16:48:17.163 iconf[1438:207] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[NSManagedObject compare:]: unrecognized selector sent to instance 0x3b11a10'
    2010-02-20 16:48:17.163 iconf[1438:207] Stack: (

【问题讨论】:

如果您可以设置调试器并准确找出它在哪一行崩溃,这将有很大帮助。如果您发布数据模型的图片也会有所帮助,以便我们清楚地看到关系。 【参考方案1】:

听起来您的数据模型(应该)如下所示:

演讲者 > 会议 标题 > 会议

Speaker 和 Title 都与 Session 有一对多关系

基于此:

我使用一个整数键来设置每个 关系。

和您的代码,看起来您正在手动管理关系。你为什么做这个?!这是复杂且不必要的。在您的 Core Data 数据模型中设置和使用真实关系。

此外,不要使用“id”作为属性名称,因为它是 Objective-C 中的关键字。

【讨论】:

【参考方案2】:

谢谢,下面是数据模型的副本。您对基本布局的看法是正确的。

http://www.freeimagehosting.net/image.php?debf5866c1.jpg

我手动设置关系的原因是因为这是第一次通过程序,所以我从三个单独的 plist(一个用于演讲者,一个用于标题,一个用于会话)进行数据的初始加载。有一个更好的方法吗?我可能根本不了解核心数据,但似乎每次创建会话实体时我只是创建了一个新的标题实体,我将在标题与会话之间建立一对一的关系,而不是一对一的关系我想要的很多关系。因此,我放入了 id 变量(我现在已将其重命名,错误没有改变)作为第一次加载到核心数据的键。在那之后,我当然会使用核心数据来管理所有这些。有没有更好的方法来做到这一点?

【讨论】:

首先,您有两个 SO 用户吗?为什么?接下来,您永远不应该发布问题的其他内容作为答案。如果合适,您可以编辑原始问题或创建新问题。 您可以从 plist 进行初始加载,或者您可以在开发期间进行初始加载,然后保存该数据库文件并将其添加到您的项目中。然后,在您发布的应用程序中,您可以将只读应用程序包中的数据库文件复制到 Documents 目录中。见***.com/questions/2265333/… 您不了解 Core Data 关系。您应该做的第一件事是为您的实体创建子类。然后,您可以通过它们的名称访问属性和关系作为对象的属性。对多关系实际上是集合,因此您可以使用在 Xcode 中创建子类时为您提供的方法添加单个对象或一组对象。 是的,我对我滥用堆栈溢出表示诚挚的歉意。我不小心匿名发布了我的第一个帖子,因此当我发布带有附加详细信息的评论时,由于评分低,我无法以自己的身份发表评论。不管怎样,我以后会做得更好。我只是找出错误。在上面我发布的代码中,我在“标题”上使用了 fetchedResultsController 来检查是否有任何结果。我摆脱了它,我很高兴去。再次感谢您对菜鸟的耐心。

以上是关于难以调试 iPhone Core Data 错误的主要内容,如果未能解决你的问题,请参考以下文章

是否可以在开发 iphone 上查看存储在 Core Data 中的数据?

JavaScript 调试常见报错以及原因

在 iPhone 应用程序关闭并重新打开之前,Core Data 信息不显示的问题

Core Data 无法删除从未插入的对象错误

Xcode Entity Core Data - NSDate 错误的年份? [复制]

(iOS Swift) 从 Core Data 获取记录返回致命错误或 nil