【问题标题】:CoreData NSSet-Like behavior for NSManagedObjects with the same values具有相同值的 NSManagedObjects 的 CoreData NSSet-Like 行为
【发布时间】: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;

【问题讨论】:

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


    【解决方案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://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;
        }
    }
    

    【讨论】:

    • 谢谢!你确定我可以毫无问题地覆盖散列函数吗?
    • 如果我覆盖 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;
      }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-05-26
      • 1970-01-01
      • 2020-12-13
      • 1970-01-01
      • 2011-11-06
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多