Iphone 使用核心数据设计聊天应用程序

Iphone 使用核心数据设计聊天应用程序,iphone,ios,database,core-data,Iphone,Ios,Database,Core Data,我正在编写一个聊天应用程序,我正在更改数据库以使用核心数据。我目前直接使用sqlite,但我想利用iCloud的功能,所以我正在切换引擎 我的主表名为Entry,具有以下属性: NSInteger type; NSDate* timestamp; NSString* username; NSString* session; NSString* body; 其中“类型”可以是: 1 - message 2 - file transfer (which then 'body' represents

我正在编写一个聊天应用程序,我正在更改数据库以使用核心数据。我目前直接使用sqlite,但我想利用iCloud的功能,所以我正在切换引擎

我的主表名为Entry,具有以下属性:

NSInteger type;
NSDate* timestamp;
NSString* username;
NSString* session;
NSString* body;
其中“类型”可以是:

1 - message
2 - file transfer (which then 'body' represents a file name in the documents folder)
3 - user joined
4 - user left
我的应用程序还支持多用户聊天(因此为什么“用户加入”/“用户离开”类型)。所有属于同一对话(仅限多人聊天)的邮件将具有有效的“会话”属性

在我的聊天历史记录中,我的问题是如何实现苹果在短信应用程序中所做的“加载更多”:我将根据
'username=%@和session is NULL'
'session=%@'
进行查询,以显示该历史记录,并使用按反向“时间戳”排序的50个限制。 然后我想有一个按钮“加载更多”,它将加载接下来的50条消息-我不知道如何处理核心数据

我的下一个问题是如何显示对话列表。现在使用原始sqlite,我对两个查询执行联接:第一个是每个用户的最后一条消息,第二个是每个多用户对话的最后一条消息。然后我按日期对它们进行排序。 由于核心数据不支持联接,我不确定如何执行此查询


谢谢

首先,你的思维模式完全错了。您不应该将核心数据视为SQL数据库。是的,大多数时候它都使用SQL,但这只是一个实现细节。你应该从对象图的角度来思考

接下来,关于“50项”问题,请看NSFetchRequest。您可以告诉它从哪里开始(fetchOffset),以及要获取多少项(fetchLimit)。你还有其他选择。如果项目总数相对较小,则可以只获取整个数组(并且一次只能获取如此多的错误-请参阅fetchBatchSize)

<>你的“加入”考虑了对象是如何相互关联的,而不是数据库表连接。不幸的是,我不明白你想通过这部分问题实现什么。但是,在形成谓词时,可以使用点表示法模拟“连接”表

编辑

创建对话对象时,可以包括与“参与者”之类的对象的对多关系,参与者是参与该对话的所有用户的集合。反过来,“用户”中的多对多关系包含用户参与的所有对话(我假设您的数据库有多个用户??)


因此,要获取特定用户参与的所有对话,您可以使用类似于“all participants.username=%@”的谓词在“Participant”上执行类似的获取操作。如果有一个应用程序可以执行完全相同的操作,下面是我的见解

首先,在编码之前,你应该仔细考虑CORADATA和多线程。如果你需要帮助,请告诉我

模型

您正在使用Coredata中的实体,可以将其视为类似于sqlite中的表,但其方式更为抽象。你应该为此付出代价

在您的案例中,我们至少可以找到三种不同的实体:用户、会话和消息。(请注意最后一个,在导入SMS框架时,我遇到了一个消息实体,您应该考虑对该实体的名称进行预处理。) coredata的一个问题是,您不能直接存储数组(可能是某些未知类型的数组),但无论如何。因此,有两种解决方案可以存储用户:一种是用comas分隔的NSString格式,另一种是简单的regex或split格式,可以提供用户数量

因此,您的模型可能看起来像:

Conversation{
     messages<-->>Message.conversation
     lastMessage<-->Message.whateverName
     //optional
     users<<-->>User.conversation
}

Message{
    conversation<<-->Conversation.messages
    whatevername<-->Conversation.lastmessage // "whatever as it does not really matter"
}

User{
    conversations<<-->>Conversation.users
}
--编辑结束

希望这有帮助


Pierre

关于问题的第二部分:我想做的是列出所有对话(显示对话列表,用户可以单击并展开以查看完整对话)。它类似于iMessage。我想展示每个独特对话的最后一条信息。我无法按用户名分组,因为用户可能会出现两次(一次在单个聊天中出现一次,另一次在组聊天中出现一次)。您想显示所有对话的最后一条消息,还是只显示某个特殊用户最后一条消息?抱歉,我不使用聊天客户端,所以我不熟悉这个类比。假设我与用户a进行了一次对话(我们交换了100条消息),与用户B进行了另一次对话(50条消息),同时与两个用户a/B进行了群聊(10条消息):我想显示一个包含3项(a、B、a/B)的列表。如果单击第一个条目-您将看到100条消息的历史记录,单击第二个条目将显示50条消息的历史记录,单击第三个条目将显示10条消息。我想模仿iMessage。我同意你的建议,但在阅读对话列表时——我如何获得要显示的最后一条消息(就像你在“消息”屏幕中所做的那样)。?谢谢。嗨,吉拉德。我稍微编辑了一下我的答案。基本上,只需添加一个名为lastMessage的一对一关系或任何您想要的关系。每次收到新消息/删除最后一条消息时,只需更新lastMessage字段。如果您不喜欢添加额外的关系,我想您可以深入研究每个会话的NSFetchRequest以查找最后一条消息,但从性能角度来看,这可能非常糟糕。希望这能帮助汉克斯-皮埃尔-这就是我最终所做的。我在删除邮件时遇到了一个小问题(我现在需要手动识别最新的邮件并更新我的对话对象),但至少我正确地获取了历史记录。谢谢@NerujaJoseph如前所述,我们只是添加了这个额外的一对一,以便以更简单的方式访问最后一条消息。这在技术上是不必要的。但和往常一样,在CS中,你必须在速度和空间之间做出选择!关于删除/添加Gilad评论的事实略有不同,我不希望他手动删除该对象。。。公平地说,我只是重新阅读了苹果的文档和
NSFetchRequest * req = [[NSFetchRequest alloc] init];
[req setEntity:[NSEntityDescription entityForName:@"Message" inManagedObjectContext:context]];
[req setPredicate:[NSPredicate predicateWithFormat:@"conversation == %@", self]]; /* did that from a Conversation object.. */
NSSortDescriptor *sort = [[NSSortDescriptor alloc] initWithKey:@"sent_date" ascending:NO];
[req setSortDescriptors:[NSArray arrayWithObject:sort]];

[sort release];
NSError * error = nil;
NSArray * messages = [context executeFetchRequest:req error:&error];
[req release];
if ([messages count] > 0) { /* sanity check */
    return [messages objectAtIndex:0];
}
return nil;