具有相同值的 NSManagedObjects 的 CoreData NSSet-Like 行为
CoreData NSSet-Like behavior for NSManagedObjects with the same values
我有一个带有这样数据模型的聊天应用程序。
User <--> Conversation <-->> Message
我现在的问题:有时,如果我从备份中获取旧消息,我的数据模型中会有两次消息。我想要一个 NSSet-Like Class 来识别消息对象是否在其属性上具有完全相同的值。我读过,我不能覆盖方法 -hash
和 -isEqual:
,所以我不知道该怎么做。任何的想法?这是一些代码...
+(void)addMessages:(NSSet<JSQMessage *> *)messages toConversation:(Conversation *)conversation
{
DataManager * dataManager = [DataManager dataManager];
NSMutableSet * storeSet = [NSMutableSet setWithCapacity:messages.count];
for (JSQMessage * jsqMessage in messages) {
Message * message = [NSEntityDescription insertNewObjectForEntityForName:CDEntityNameMessage inManagedObjectContext:[dataManager managedObjectContext]];
message.senderId = jsqMessage.senderId;
message.senderDisplayName = jsqMessage.senderDisplayName;
message.text = jsqMessage.text;
message.date = jsqMessage.date;
[storeSet addObject:message];
}
[conversation addMessages:storeSet];
NSError *error;
if (![[dataManager managedObjectContext] save:&error]) {
NSLog(@"Something went wrong: %@", [error localizedDescription]);
} else {
//Saved successfull
}
}
而 Conversation
-addMessages:
方法是从 Xcode/CoreData
自动生成的方法
- (void)addMessages:(NSSet<Message *> *)values;
一种方法是为您的实体添加一个或多个属性的唯一约束。但是,此功能是从 iOS 9 添加的。这是解释它的 WWDC 视频的 link:
https://developer.apple.com/videos/play/wwdc2015/220/
作为最后一个选项,如果符合您的逻辑和要求,您始终可以覆盖散列和等于。
您的哈希方法可能如下所示:
- (NSUInteger)hash
{
NSInteger hashResult = 0;
for (NSObject *ob in self)
{
hashResult ^= [ob hash];
}
}
这不是散列函数的最佳实现。查看此答案:
对于 isEqual 方法,它可能类似于:
- (BOOL)isEqual:(id)object
{
if (self == object)
{
return YES;
}
if (object == nil || ![object isKindOfClass:[JSQMessage class]])
{
return NO;
}
JSQMessage *jsqMessage = (JSQMessage*)object;
//You can have more parameters here based on your business logic
if (self.message != jsqMessage.message && self.date != jsqMessage.date)
{
return NO;
}
}
我现在做的是手动检查我的 MOC 中是否有具有相同属性的对象。如果有的话,我会跳过创建。我知道,这有点低效,但按照我预期的消息数量,这应该没问题。
NSFetchRequest * fr = [NSFetchRequest fetchRequestWithEntityName:CDEntityNameMessage];
[fr setPredicate:[NSPredicate predicateWithFormat:@"text == %@ AND date == %@ AND conversation.user.objectId == %@", message.text, message.date, chatpartner.objectId]];
NSArray * results = [[self managedObjectContext] executeFetchRequest:fr error:nil];
if (results && results.count > 0) {
continue;
}
我有一个带有这样数据模型的聊天应用程序。
User <--> Conversation <-->> Message
我现在的问题:有时,如果我从备份中获取旧消息,我的数据模型中会有两次消息。我想要一个 NSSet-Like Class 来识别消息对象是否在其属性上具有完全相同的值。我读过,我不能覆盖方法 -hash
和 -isEqual:
,所以我不知道该怎么做。任何的想法?这是一些代码...
+(void)addMessages:(NSSet<JSQMessage *> *)messages toConversation:(Conversation *)conversation
{
DataManager * dataManager = [DataManager dataManager];
NSMutableSet * storeSet = [NSMutableSet setWithCapacity:messages.count];
for (JSQMessage * jsqMessage in messages) {
Message * message = [NSEntityDescription insertNewObjectForEntityForName:CDEntityNameMessage inManagedObjectContext:[dataManager managedObjectContext]];
message.senderId = jsqMessage.senderId;
message.senderDisplayName = jsqMessage.senderDisplayName;
message.text = jsqMessage.text;
message.date = jsqMessage.date;
[storeSet addObject:message];
}
[conversation addMessages:storeSet];
NSError *error;
if (![[dataManager managedObjectContext] save:&error]) {
NSLog(@"Something went wrong: %@", [error localizedDescription]);
} else {
//Saved successfull
}
}
而 Conversation
-addMessages:
方法是从 Xcode/CoreData
- (void)addMessages:(NSSet<Message *> *)values;
一种方法是为您的实体添加一个或多个属性的唯一约束。但是,此功能是从 iOS 9 添加的。这是解释它的 WWDC 视频的 link: https://developer.apple.com/videos/play/wwdc2015/220/
作为最后一个选项,如果符合您的逻辑和要求,您始终可以覆盖散列和等于。
您的哈希方法可能如下所示:
- (NSUInteger)hash
{
NSInteger hashResult = 0;
for (NSObject *ob in self)
{
hashResult ^= [ob hash];
}
}
这不是散列函数的最佳实现。查看此答案:
对于 isEqual 方法,它可能类似于:
- (BOOL)isEqual:(id)object
{
if (self == object)
{
return YES;
}
if (object == nil || ![object isKindOfClass:[JSQMessage class]])
{
return NO;
}
JSQMessage *jsqMessage = (JSQMessage*)object;
//You can have more parameters here based on your business logic
if (self.message != jsqMessage.message && self.date != jsqMessage.date)
{
return NO;
}
}
我现在做的是手动检查我的 MOC 中是否有具有相同属性的对象。如果有的话,我会跳过创建。我知道,这有点低效,但按照我预期的消息数量,这应该没问题。
NSFetchRequest * fr = [NSFetchRequest fetchRequestWithEntityName:CDEntityNameMessage];
[fr setPredicate:[NSPredicate predicateWithFormat:@"text == %@ AND date == %@ AND conversation.user.objectId == %@", message.text, message.date, chatpartner.objectId]];
NSArray * results = [[self managedObjectContext] executeFetchRequest:fr error:nil];
if (results && results.count > 0) {
continue;
}