gpt4 book ai didi

objective-c - 核心数据查找或创建最有效的方式

转载 作者:太空狗 更新时间:2023-10-30 03:28:36 26 4
gpt4 key购买 nike

我有大约 10000 个实体“Message”的对象。当我添加一个新的“Message”时,我想先看看它是否存在——如果它确实存在,则只更新它的数据,如果不存在,则创建它。

现在“查找或创建”算法的工作原理是将所有消息对象“objectID”保存在一个数组中,然后过滤它们并获取具有 existingObjectWithID 的消息:错误:

这工作正常,但在我的情况下,当我使用 existingObjectWithID 获取“消息”时:然后尝试通过设置“消息”对象的属性并调用保存来设置和保存属性:在它的上下文中,它没有正确保存它。有没有人遇到过这样的问题?

是否有更有效的方法来制作查找或创建算法?

最佳答案

首先,Message 是 CoreData 实体的“错误”名称,因为苹果在内部使用它,它会在以后的开发中引起问题。
您可以阅读更多相关信息 HERE

我注意到这里所有建议的解决方案都使用数组或获取请求。
您可能需要考虑基于字典的解决方案...

在单线程/上下文应用程序中,通过将新插入的对象(Message 类型)添加到缓存(字典)并使用现有的缓存预填充缓存,可以轻松实现这一点对象 ID 和键映射。

考虑这个接口(interface):

@interface UniquenessEnforcer : NSObject

@property (readonly,nonatomic,strong) NSPersistentStoreCoordinator* coordinator;
@property (readonly,nonatomic,strong) NSEntityDescription* entity;
@property (readonly,nonatomic,strong) NSString* keyProperty;
@property (nonatomic,readonly,strong) NSError* error;

- (instancetype) initWithEntity:(NSEntityDescription *)entity
keyProperty:(NSString*)keyProperty
coordinator:(NSPersistentStoreCoordinator*)coordinator;

- (NSArray*) existingObjectIDsForKeys:(NSArray*)keys;
- (void) unregisterKeys:(NSArray*)keys;
- (void) registerObjects:(NSArray*)objects;//objects must have permanent objectIDs
- (NSArray*) findOrCreate:(NSArray*)keys
context:(NSManagedObjectContext*)context
error:(NSError* __autoreleasing*)error;
@end

流程:

1) 在应用程序启动时,分配一个“唯一性执行器”并填充您的缓存:

//private method of uniqueness enforcer
- (void) populateCache
{
NSManagedObjectContext* context = [[NSManagedObjectContext alloc] init];
context.persistentStoreCoordinator = self.coordinator;

NSFetchRequest* r = [NSFetchRequest fetchRequestWithEntityName:self.entity.name];
[r setResultType:NSDictionaryResultType];

NSExpressionDescription* objectIdDesc = [NSExpressionDescription new];
objectIdDesc.name = @"objectID";
objectIdDesc.expression = [NSExpression expressionForEvaluatedObject];
objectIdDesc.expressionResultType = NSObjectIDAttributeType;

r.propertiesToFetch = @[self.keyProperty,objectIdDesc];

NSError* error = nil;

NSArray* results = [context executeFetchRequest:r error:&error];
self.error = error;
if (results) {
for (NSDictionary* dict in results) {
_cache[dict[self.keyProperty]] = dict[@"objectID"];
}
} else {
_cache = nil;
}
}

2)当你需要测试是否存在时,只需使用:

- (NSArray*) existingObjectIDsForKeys:(NSArray *)keys
{
return [_cache objectsForKeys:keys notFoundMarker:[NSNull null]];
}

3) 当您想实际获取对象并创建丢失的对象时:

- (NSArray*) findOrCreate:(NSArray*)keys
context:(NSManagedObjectContext*)context
error:(NSError* __autoreleasing*)error
{
NSMutableArray* fullList = [[NSMutableArray alloc] initWithCapacity:[keys count]];
NSMutableArray* needFetch = [[NSMutableArray alloc] initWithCapacity:[keys count]];

NSManagedObject* object = nil;
for (id<NSCopying> key in keys) {
NSManagedObjectID* oID = _cache[key];
if (oID) {
object = [context objectWithID:oID];
if ([object isFault]) {
[needFetch addObject:oID];
}
} else {
object = [NSEntityDescription insertNewObjectForEntityForName:self.entity.name
inManagedObjectContext:context];
[object setValue:key forKey:self.keyProperty];
}
[fullList addObject:object];
}

if ([needFetch count]) {
NSFetchRequest* r = [NSFetchRequest fetchRequestWithEntityName:self.entity.name];
r.predicate = [NSPredicate predicateWithFormat:@"SELF IN %@",needFetch];
if([context executeFetchRequest:r error:error] == nil) {//load the missing faults from store
fullList = nil;
}
}

return fullList;
}

在此实现中,您需要自己跟踪对象的删除/创建。
成功保存后,您可以为此使用注册/注销方法(简单实现)。
您可以通过挂接到上下文“保存”通知并使用相关更改更新缓存来使其更加自动化。

多线程的情况要复杂得多(考虑到性能时,相同的接口(interface)但完全不同的实现)。
例如,你必须让你的执法者在将新元素返回到请求上下文之前保存它们(到商店),否则它们没有永久 ID,即使你调用“获取永久 ID”,请求上下文最终也可能不会保存.
您还需要使用某种(并行或串行)调度队列来访问您的缓存字典。

一些数学:

给定:
10K(10*1024)个唯一键对象
平均 key 长度为 256[byte]
objectID 长度为 128[byte]
我们正在看:
10K*(256+128) =~ 4[MB] 内存

这可能是一个高估计,但你应该考虑到这一点......

关于objective-c - 核心数据查找或创建最有效的方式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22247059/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com