devise使用核心数据的聊天应用程序

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

我的主表被称为Entry具有以下属性:

NSInteger type; NSDate* timestamp; NSString* username; NSString* session; NSString* body; 

其中“types”可以是:

 1 - message 2 - file transfer (which then 'body' represents a file name in the documents folder) 3 - user joined 4 - user left 

我的应用程序还支持多用户聊天(因此为什么'用户join'/'用户离开'types)。 所有消息属于同一个对话(仅限多聊天),将具有有效的“会话”属性。

在我的聊天logging中,我的问题是如何实现苹果在短信应用程序中的“加载更多”:我将根据'username=%@ AND session IS NULL''session=%@'进行查询以显示历史logging并使用50个“时间戳”sorting的LIMIT。 然后,我想要一个button“加载更多”,将加载下50个消息 – 我不知道如何与核心数据。

我的下一个问题是如何显示对话列表。 现在使用原始的sqlite,我对2个查询执行一个连接:第一个是每个用户的最后一个消息,第二个是每个多用户对话的最后一个消息。 然后我按datesorting。 由于核心数据不支持连接,我不知道如何执行此查询。

谢谢

有一个完全相同的应用程序,这里是我的见解。

首先你应该在编码之前明智地考虑coredata和multithreading。 如果你需要帮助,请告诉我。

该模型

您正在使用Coredata中的实体,可以像sqlite中的表格那样考虑实体,但采用更抽象的方式。 您应该查看苹果的文档 。

我们可以在您的案例中find至less三个不同的实体:用户,对话和消息。 (要小心最后一个,导入SMS框架时,我有一个名为消息的实体的问题,你应该考虑前缀实体的名称..)

coredata的一个问题是,你不能直接存储数组(可能有一些未知的types),但无论如何。 因此,有两种解决scheme来存储你的用户:无论是在NSString中,当他们将被逗号分隔和一个简单的正则expression式或拆分会给你的用户数量..

所以你的模型可能看起来像:

 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 } 

对话必须与消息和消息具有多对多的关系才能与对话build立一对一的关系。

– 编辑

如果要显示对话的最后一条消息,就像消息应用程序(或我的应用程序),则可以添加一条消息关系。 它不会在数据库/ coredata中存储两次消息。 事实上,你创build了一个coredata对象(在本例中是一个消息),并将其添加到对话中,内部发生的是对话存储该对象的coredata ID。 为此消息添加一个关系(lastMessage)将只存储另一个ID,而不是另一个对象。

– 编辑结束

用户略有不同,因为他们可以是多个对话的一部分(因为组对话),这就是为什么你需要一个多对多的关系。

您可以添加尽可能多的属性,但这是最低要求!

  1. 履行

那么在你的代码中,如果你想模仿iMessage的行为,下面是我做的:

在第一个控制器中,你可以看到所有的对话:使用一个NSFetchedResultController。 查询应该只关于实体对话。

当点击一行时,我所做的是新视图有对话对象和另一个NSFtechedResultController。 然后,我只查询实体消息,但用谓词指定我只想要这个对话。

如果您想查看我的应用程序以查看stream动性, 请转至此链接。

编辑

  1. 代码片段查找对话的最后一个消息

注意:在find更好的方法之前,这是一个临时答案(即使用提取的属性时)

 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; 

– 编辑结束

希望这个帮助!

皮埃尔

首先,你的心智模式是错的。 您不应该将核心数据视为SQL数据库。 是的,大多数情况下,它使用SQL,但它只是一个实现细节。 你应该考虑对象图。

接下来,为你的“50项”问题,看看NSFetchRequest。 您可以告诉它从哪里开始(fetchOffset),以及要获取多less项(fetchLimit)。 还有其他的select。 如果您的项目总数相对较less,则可以只读取整个数组(并且一次只能出错很多 – 请参阅fetchBatchSize)。

对于你的“连接”,考虑对象如何相互关联,而不是数据库表连接。 不幸的是,我不明白你想用问题的这个部分来达到什么目的。 但是,在形成谓词时,可以使用点符号模仿“连接”表。

编辑

当您创build对话对象时,您可以包含一对多的关系,如“参与者”,这将成为参与对话的所有用户的集合。 在“用户”中也包含所有用户参与的对话(我假设你的数据库有多个用户?),这也是一个多对多的关系。

因此,要获得特定用户参与的所有对话,可以使用类似于“ALL participants.username =%@”的谓词来执行“参与者”