查找或创建独特的核心数据实体

发布于 2024-10-17 10:06:54 字数 1201 浏览 3 评论 0原文

核心数据驱动应用程序的常见场景是从后备存储中获取唯一的对象。如果存在具有某一唯一属性的对象,则返回该对象,如果不返回新创建的对象。我发现自己一遍又一遍地写同样的东西,所以我用一种方便的方法包装它。但这看起来太微不足道了,我是不是在重新发明轮子?有没有一种更简单、开箱即用的方法来实现这一目标?

干杯,
EP

+(id)uniqueEntityfForName:(NSString *)name 
                withValue:(id)value 
                   forKey:(NSString *)key
   inManagedObjectContext:(NSManagedObjectContext *)context {

    NSFetchRequest *request = [[[NSFetchRequest alloc] init] autorelease];    
    request.entity = [NSEntityDescription entityForName:name inManagedObjectContext:context];
    request.predicate = [NSPredicate predicateWithFormat:[key stringByAppendingString:@" == %@"], value];
    NSArray *result = [context executeFetchRequest:request error:nil];

    id entity = [result lastObject];
    if (entity == nil) {
        entity = [NSEntityDescription insertNewObjectForEntityForName:name inManagedObjectContext:context];
        [entity setValue:value forKey:key];
    } else {
        entity = [result lastObject];
    }

    return entity;
}

我使用这样的方法:

SomeEntity *entity = [CDUtils uniqueEntityfForName:@"SomeEntity" withValue:@"foo" forKey:@"bar" inManagedObjectContext:context];

A common scenario for core data driven apps is getting a unique object out of the backing store. If the object with a certain unique property exists, return that one, if it doesn't return a newly create one. I found myself writing the same thing over and over, so I wrapped it in a convenience method. But this seems so trivial, am I reinventing the wheel here? Is there a simpler, out-of-the-box way to achieve this?

Cheers,
EP

+(id)uniqueEntityfForName:(NSString *)name 
                withValue:(id)value 
                   forKey:(NSString *)key
   inManagedObjectContext:(NSManagedObjectContext *)context {

    NSFetchRequest *request = [[[NSFetchRequest alloc] init] autorelease];    
    request.entity = [NSEntityDescription entityForName:name inManagedObjectContext:context];
    request.predicate = [NSPredicate predicateWithFormat:[key stringByAppendingString:@" == %@"], value];
    NSArray *result = [context executeFetchRequest:request error:nil];

    id entity = [result lastObject];
    if (entity == nil) {
        entity = [NSEntityDescription insertNewObjectForEntityForName:name inManagedObjectContext:context];
        [entity setValue:value forKey:key];
    } else {
        entity = [result lastObject];
    }

    return entity;
}

I use this method like this:

SomeEntity *entity = [CDUtils uniqueEntityfForName:@"SomeEntity" withValue:@"foo" forKey:@"bar" inManagedObjectContext:context];

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

静赏你的温柔 2024-10-24 10:06:54

相当标准。我的核心数据实体有很多方法,例如 [aStudent enrollmentForId:(long long)idValue createIfMissing:YES]

我还想插入 mogenerator ,这可以消除核心数据的很多痛苦。除此之外,它还为数据模型中定义的每个获取请求生成一个工厂方法。因此,在模型中创建一个获取谓词,例如,

thingies: thingyId == $forThingyId

产生一个匹配的类方法:

+(NSArray *)fetchThingies:(NSManagedObjectContext *)moc forThingyId:(id)thingyId

...它执行您在那里编写的前半部分内容。 类似的包装器都很简单。

-(Thingy*)thingyForIdValue:(long long)thingyId

这样,在任何包含托管对象上下文的类中(例如“父”实体或应用程序委托等),编写

Pretty standard. My core data entities have lots of methods like [aStudent enrollmentForId:(long long)idValue createIfMissing:YES].

I'd also like to plug mogenerator , which removes much pain from Core Data. Among other things, it generates a factory method for every fetch request defined in the data model. So making a fetch predicate in the model like, e.g,

thingies: thingyId == $forThingyId

yields a matching class method:

+(NSArray *)fetchThingies:(NSManagedObjectContext *)moc forThingyId:(id)thingyId

...which does the first half of what you've written up there. A wrapper like

-(Thingy*)thingyForIdValue:(long long)thingyId

is then trivial to write, in whatever class holds your managedObjectContext (eg. a "parent" entity, or app delegate, or whatever.)

吻泪 2024-10-24 10:06:54

更灵活的解决方案是使用 Blocks 让调用者在比较两个列表时处理 3 种情况。

  1. 匹配集
  2. 主机不匹配集
  3. 本地不匹配集

因此,在以同步方式插入或添加到数据存储时无需创建类似的函数。

typedef void (^objectOperationBlock)(NSManagedObjectContext *context,
                                 NSDictionary *hostObjectData,
                                 NSManagedObject *localManagedObject);

- (void) insertUniquely:(NSArray *)rawDataArray 
                 entity:(NSString *)entity 
           matchedBlock:(objectOperationBlock)matchedOperation
     hostUnmatchedBlock:(objectOperationBlock)hostUnmatchedOperation
    localUnmatchedBlock:(objectOperationBlock)localUnmatchedOperation
                  error:(NSError **)outError;

完整的实现可以在这里找到: http:// /emplementation.blogspot.com/2011/12/importing-data-into-core-data-while.html

A more flexible solution is to use Blocks to let the caller to handle 3 situations when comparing two lists.

  1. Matching Sets
  2. Host unmatched sets
  3. Local unmatched sets

Therefore, there is no need to create similar functions when inserting in a syncing fashion or additions to the data store.

typedef void (^objectOperationBlock)(NSManagedObjectContext *context,
                                 NSDictionary *hostObjectData,
                                 NSManagedObject *localManagedObject);

- (void) insertUniquely:(NSArray *)rawDataArray 
                 entity:(NSString *)entity 
           matchedBlock:(objectOperationBlock)matchedOperation
     hostUnmatchedBlock:(objectOperationBlock)hostUnmatchedOperation
    localUnmatchedBlock:(objectOperationBlock)localUnmatchedOperation
                  error:(NSError **)outError;

A full implementation can be found here: http://emplementation.blogspot.com/2011/12/importing-data-into-core-data-while.html

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文