简体   繁体   English

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

[英]CoreData NSSet-Like behavior for NSManagedObjects with the same values

I have a Chat-App with a Data-Modell like this. 我有一个带有这样的数据模型的聊天应用程序。

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

My Problem now: Sometimes, if I get old messages from a Backup, I have Messages twice in my DataModel. 我现在的问题:有时,如果我从备份中收到旧消息,则我的DataModel中有两次Messages。 I'd like to have a NSSet-Like Class which recognizes, if a Message-Object has exactly the same values on it's properties. 我想拥有一个NSSet-Like类,该类可以识别Message-Object是否具有完全相同的属性值。 I've read, that I must not override the methods -hash and -isEqual: , so I don't know how to do it. 我已经读过,我不能重写方法-hash-isEqual:所以我不知道该怎么做。 Any Idea? 任何想法? Here is some code... 这是一些代码...

+(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
}
}

And the Conversation -addMessages: Method is the one automatically generated from Xcode/CoreData Conversation -addMessages:方法是从Xcode / CoreData自动生成的方法

- (void)addMessages:(NSSet<Message *> *)values;

One way of doing it would be to add unique constraints on your entity for one or more attributes. 一种方法是在您的实体上为一个或多个属性添加唯一约束。 But, this feature was added from iOS 9. Here's the link to the WWDC video explaining it: https://developer.apple.com/videos/play/wwdc2015/220/ 但是,此功能是iOS 9的新增功能。这是WWDC视频的解释链接: https : //developer.apple.com/videos/play/wwdc2015/220/

As a final option, you can always override hash and equal, if that suits your logic and requirements. 最后一个选择是,如果适合您的逻辑和要求,则可以始终覆盖哈希和等于。

You hash method could look something like this: 您的哈希方法可能如下所示:

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

This is not the best implementation of a hash function. 这不是哈希函数的最佳实现。 Check out this answer: https://stackoverflow.com/a/5915445/2696922 看看这个答案: https : //stackoverflow.com/a/5915445/2696922

For the isEqual method, it could look something like: 对于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;
    }
}

What I do now is checking manually, if there is a Object with same Attributes in my MOC. 我现在要做的是手动检查,如果我的MOC中有一个具有相同属性的对象。 If there is one, I skip the creation. 如果有一个,我将跳过创建。 I know, it is a bit inefficient but with my expected number of messages, this should be no problem. 我知道,这效率不高,但根据我的预期消息数量,这应该没问题。

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;
  }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM