【问题标题】:Should I fetch all Core Data entities upfront on iPhone?我应该在 iPhone 上预先获取所有核心数据实体吗?
【发布时间】:2010-09-03 01:10:42
【问题描述】:

我正在构建一个具有 chatView 的社交应用程序。消息是一个实体。在 usersViewController (rootViewController) 上,我只想显示来自每个用户的未读消息数。但是在 chatView 上,我想显示我和所选用户之间发送的消息。

我应该如何从 Core Data 中获取消息?

  1. 有没有办法以 userIds 作为键将它们全部提取到 NSMutableDictionary 中,每个都指向消息实体的 NSMutableArray?或者,我是否必须获取所有消息,然后使用 Objective-C 遍历它们以按描述排列它们?

  2. 无论哪种方式,我都应该在 appDelegate 中预先加载它们吗?或者,我应该只在查看相应的聊天视图时加载特定对话的消息吗?

  3. 要获得未读计数,我是否应该遍历获取的消息实体以创建指向计数值的用户 ID 键的 NSMutableDictionary?或者,我应该创建一个类似于按 userId 分组的 SQL 总和查询的谓词(Core Data 甚至可能吗?)?

  4. 我是否应该创建一个模型,将其命名为 UnreadMessageCount,用于存储我从每个用户收到的未读消息的数量以及对 User 模型的引用?我想在应用程序的第一页上显示所有未读消息,这样可以加快查询速度。但是接收消息会更慢,因为我不仅需要将其添加到 Message 模型中,而且还必须在 UnreadMessageCount 模型中增加该用户的计数。此外,数据会有点重复。此外,每次应用程序启动时,我只会查询所有消息计数一次,但每次收到新消息并且不在该用户的 chatView 页面上时,我都会进行查询以更新未读消息计数。

请填写 iPhone 内存管理和核心数据的可能性和性能。另外,请就设计此功能的最佳方式发表您的意见。

谢谢!

马特

【问题讨论】:

    标签: iphone core-data chat


    【解决方案1】:

    要获取消息计数,我会向托管对象上下文询问给定某个获取请求的消息计数,例如,计算某个用户的消息:

    NSFetchRequest *request = [[[NSFetchRequest alloc] init] autorelease];
    
    NSEntityDescription *entity = [NSEntityDescription entityForName:@"Message" inManagedObjectContext:context];
    [request setEntity:entity];
    
    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"user == %@", user];
    [request setPredicate:predicate];
    
    NSInteger count = [context countForFetchRequest:request error:nil];
    

    这里我假设Message 实体具有user 关系。

    要获取同一用户的实际消息,我只需将最后一行替换为:

    NSArray *messages = [context executeFetchRequest:request error:nil];
    

    【讨论】:

    • 我喜欢这个解决方案,因为它避免了将消息加载到内存中。根据用户的数量,这应该会很好地执行。尽管不鼓励在示例中将error: 设置为nil,但人们喜欢复制和粘贴太多:)
    • 我通常把正确的错误处理留给读者作为练习;)但是你是对的,人们复制/粘贴太多了。
    • 这很棒。感谢您提供源代码。如果我想从我在 usersView 上加载的每个用户获取未读消息计数怎么办?我会为每个用户循环这段代码,还是有办法通过一次执行获取请求来获取它,比如 sum, groupby user sql query where message.unread = 1?
    • 我认为将 autorelease 与 init 放在同一行是不好的做法。你可以在 99% 的时间里逃脱惩罚,但当它咬你时,几乎不可能追查到它。 Autorelease 应该像 release 一样使用,即你应该只在你完成对象后发送它。
    • @MattDiPasquale 您可以相应地调整 NSFetchRequest 的 NSPredicate,例如 @"user == %@ AND unread == YES" 并对该请求进行计数。
    【解决方案2】:

    当您使用 CoreData(尤其是示例中的简单结构)时,iPhone 通常可以很好地管理资源。因此,要回答您的问题,我认为您应该这样做:

    1. 您需要获取所有用户,然后遍历它们并创建字典键,该键将指向每个 user 实体的 messages 属性
    2. 您不应该改用NSFetchedResultsController,它可以有效地加载请求的实体并执行所有必需的预取以优化表格视图中的显示
    3. 上面的答案可能是关于计数的方法。在您的实体上创建适当的索引将使其变得快如闪电。

    【讨论】:

    • 酷,谢谢!为了澄清#2,我不应该在appDelegate中预先加载它们,而是在为该用户加载chatView时只请求特定用户的消息?如果是这样,那么无论如何我都不需要做#1。如果我想在 usersView 上显示所有用户的未读计数,那么我会为每个用户循环 @Martin 的代码吗?或者我可以在一个请求中做到这一点吗?
    • 哦,嘿,是的,你不需要#1,我认为这是一个无关的问题。是的,有一种方法可以在一个请求中执行此操作,只需删除“user = %@”谓词并添加一些检查消息标志的内容,具体取决于您的数据模型可能是 "isUnread = 1" 或类似的东西
    猜你喜欢
    • 2011-06-06
    • 1970-01-01
    • 2011-02-14
    • 1970-01-01
    • 1970-01-01
    • 2014-01-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多