具有相同值的NSManagedObjects的CoreData NSSet-Like行为

时间:2016-07-26 12:08:41

标签: ios objective-c iphone core-data nsset

我有一个像这样的Data-Modell的Chat-App。

User <--> Conversation <-->> Message

我现在的问题:有时候,如果我从备份中获取旧消息,我的DataModel中会有两次消息。我希望有一个NSSet-Like类,如果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;

2 个答案:

答案 0 :(得分:0)

这样做的一种方法是为您的实体添加一个或多个属性的唯一约束。但是,这个功能是从iOS 9添加的。这是WWDC视频的链接,解释了它: https://developer.apple.com/videos/play/wwdc2015/220/

作为最后一个选项,如果符合您的逻辑和要求,您可以始终覆盖哈希和相等。

你的哈希方法看起来像这样:

- (NSUInteger)hash 
{
    NSInteger hashResult = 0;
    for (NSObject *ob in self)
    {
        hashResult ^= [ob hash];
    }
}

这不是哈希函数的最佳实现。看看这个答案:https://stackoverflow.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;
    }
}

答案 1 :(得分:0)

我现在做的是手动检查,如果我的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;
  }