我正在尝试在我的应用程序中实现聊天功能,使用Realm.io作为内部数据库来存储聊天消息,并使用PubNub来发送和接收消息。我有ChatSessions,它定义了发送消息的通道,以及ChatMessages,它们代表消息本身,并保存对消息文本的引用,消息发送的日期,消息发送者的名称,以及消息所属的ChatSession。
在下面的代码中,我正在从通道中收到的PNMessage初始化ChatMessage,并指定所有字段。我遇到的问题是,当Realm将消息写入数据库时,ChatMessage的会话字段设置为nil,尽管事实上在调用write方法之前,会话字段具有指定的有效ChatSession。
- (void)createChatMessageFromMessage:(PNMessage *)message
{
NSDictionary *msgDict = message.message;
ChatMessage *chatMessage = [[ChatMessage alloc] init];
chatMessage.text = [msgDict objectForKey:@"text"];
chatMessage.dateSent = [NSDate dateWithTimeIntervalSinceReferenceDate:[[msgDict objectForKey:@"dateSent"] floatValue]];
chatMessage.sender = [msgDict objectForKey:@"sender"];
NSPredicate *sessionPredicate = [NSPredicate predicateWithFormat:@"sessionName = %@", [msgDict objectForKey:@"session"]];
RLMArray *matches = [ChatSession objectsWithPredicate:sessionPredicate];
if ([matches count] == 1) {
chatMessage.session = [matches firstObject];
NSLog(@"Added chatMessage with session name: %@", chatMessage.session.sessionName);
} else {
NSLog(@"Error: ChatSession with name %@ not found in db.", [msgDict objectForKey:@"session"]);
return;
}
[NSThread detachNewThreadSelector:@selector(writeToDefaultRealm:) toTarget:self withObject:chatMessage];
}
#pragma mark - Saving to Realm
- (void)writeToDefaultRealm:(RLMObject *)object
{
RLMRealm *defaultRealm = [RLMRealm defaultRealm];
[defaultRealm beginWriteTransaction];
[defaultRealm addObject:object];
if ([object isKindOfClass:[ChatMessage class]]) {
[((ChatMessage *)object).session.messages addObject:object];
NSLog(@"Wrtiting message with text: %@ with session name: %@", ((ChatMessage *)object).text, ((ChatMessage *)object).session.sessionName);
} else {
NSLog(@"Writing session with name: %@", ((ChatSession *)object).sessionName);
}
[defaultRealm commitWriteTransaction];
}
设置chatMessage.session后的NSLog正确记录了我想要的内容。 chatMessage具有正确的会话名称。但是,writeToDefaultRealm中的NSLog会正确记录消息文本,但会记录session.sessionName的nil值。
有谁知道为什么会话字段被设置为nil?谢谢
修改
ChatMessage.h
#import <Realm/Realm.h>
@class ChatSession;
@interface ChatMessage : RLMObject
// Add properties here to define the model
@property NSString *text;
@property NSDate *dateSent;
@property NSString *sender;
@property ChatSession *session;
@end
// This protocol enables typed collections. i.e.:
// RLMArray<ChatMessage>
RLM_ARRAY_TYPE(ChatMessage)
ChatSession.h
#import "ChatMessage.h"
#import <Realm/Realm.h>
@interface ChatSession : RLMObject
// Add properties here to define the model
@property NSDate *dateOpened;
@property NSDate *dateUpdated;
@property NSString *sessionName;
@property NSString *myAlias;
@property NSString *theirAlias;
@property RLMArray<ChatMessage> *messages;
@end
// This protocol enables typed collections. i.e.:
// RLMArray<ChatSession>
RLM_ARRAY_TYPE(ChatSession)
答案 0 :(得分:0)
Realm当前不支持在写入事务之外分配RLMObject属性。因此,当您执行chatMessage.session = [matches firstObject];
时,因为session
是RLMObject
属性(ChatSession
),所以必须在写入事务中完成。这是一个可能的解决方案:
- (void)createChatMessageFromMessage:(PNMessage *)message
{
NSDictionary *msgDict = message.message;
ChatMessage *chatMessage = [[ChatMessage alloc] init];
chatMessage.text = [msgDict objectForKey:@"text"];
chatMessage.dateSent = [NSDate dateWithTimeIntervalSinceReferenceDate:[[msgDict objectForKey:@"dateSent"] floatValue]];
chatMessage.sender = [msgDict objectForKey:@"sender"];
NSPredicate *sessionPredicate = [NSPredicate predicateWithFormat:@"sessionName = %@", [msgDict objectForKey:@"session"]];
RLMArray *matches = [ChatSession objectsWithPredicate:sessionPredicate];
if ([matches count] == 1) {
RLMRealm *defaultRealm = [RLMRealm defaultRealm];
[defaultRealm beginWriteTransaction];
chatMessage.session = [matches firstObject];
[chatMessage.session.messages addObject:chatMessage];
[defaultRealm addObject:chatMessage];
[defaultRealm commitWriteTransaction];
NSLog(@"Added chatMessage with session name: %@", chatMessage.session.sessionName);
} else {
NSLog(@"Error: ChatSession with name %@ not found in db.", [msgDict objectForKey:@"session"]);
return;
}
}