具有相同值的 NSManagedObjects 的 CoreData NSSet-Like 行为
Posted
技术标签:
【中文标题】具有相同值的 NSManagedObjects 的 CoreData NSSet-Like 行为【英文标题】:CoreData NSSet-Like behavior for NSManagedObjects with the same values 【发布时间】:2016-07-26 12:08:40 【问题描述】:我有一个像这样的数据模型的聊天应用程序。
User <--> Conversation <-->> Message
我现在的问题:有时,如果我从备份中收到旧消息,我的 DataModel 中有两次消息。我想要一个类似 NSSet 的类,它可以识别 Message-Object 的属性是否具有完全相同的值。我读过,我不能重写方法-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;
【问题讨论】:
【参考方案1】:一种方法是为您的实体添加一个或多个属性的唯一约束。但是,这个功能是从 ios 9 添加的。这里是 WWDC 视频的链接解释它: https://developer.apple.com/videos/play/wwdc2015/220/
作为最后一个选项,如果符合您的逻辑和要求,您始终可以覆盖 hash 和 equal。
你的哈希方法可能看起来像这样:
- (NSUInteger)hash
NSInteger hashResult = 0;
for (NSObject *ob in self)
hashResult ^= [ob hash];
这不是哈希函数的最佳实现。看看这个答案:https://***.com/a/5915445/2696922
对于 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;
【讨论】:
谢谢!你确定我可以毫无问题地覆盖散列函数吗? 如果我覆盖 isEqual,我的应用程序将崩溃。实体“消息”的“消息”类非法覆盖 NSManagedObject -isEqual: 很抱歉我说你可以覆盖哈希和 isEqual 是错误的。但是,您可以做的是创建另一个具有不同名称的方法并将您的 isEqual 逻辑移到那里。您可以忽略哈希方法,因为您只想检查两个对象是否具有相同的数据。看看这是否有效。【参考方案2】:我现在做的是手动检查,如果我的 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;
【讨论】:
以上是关于具有相同值的 NSManagedObjects 的 CoreData NSSet-Like 行为的主要内容,如果未能解决你的问题,请参考以下文章