核心数据查询在托管对象上下文中插入新对象

Posted

技术标签:

【中文标题】核心数据查询在托管对象上下文中插入新对象【英文标题】:Core data query inserts new objects in managed object context 【发布时间】:2014-09-24 18:44:44 【问题描述】:

我的 OSX 应用程序中有一个方法可以获取给定类型的所有元素(GEElementType 是一个枚举)。它在大多数情况下都可以正常工作,但在某些情况下[NSManagedObjectContext executeFetchRequest:error:] 最终会调用[NSManagedObject initWithEntity:insertIntoManagedObjectContext:] 多次向 MOC 添加新对象...这是预期的行为吗?我可以始终如一地重现这一点,但我不明白为什么会这样。

这是一段代码摘录:

+ (NSArray*)elementsOfType:(GEElementType)elementType

    return [GEElement findAllObjectsWithPredicate:[NSPredicate predicateWithFormat:@"elemtype == %d", elementType]];


+ (NSArray*)findAllObjectsWithPredicate:(NSPredicate*)predicate

    NSManagedObjectContext* context = [GEDataManager sharedInstance].managedObjectContext;

    NSEntityDescription* entity = [self entityDescription];
    NSFetchRequest* request = [[NSFetchRequest alloc] init];
    [request setEntity:entity];
    [request setPredicate:predicate];

    NSError* error = nil;
    NSArray* result = [context executeFetchRequest:request error:&error];
    if (error)
    
        NSLog(@"%@", error.localizedDescription);
    

    return result;

如果有什么不同,我将使用 Mogenerator 和自定义基础 NSManagedObject 子类。

我在子类的 init 中添加了一个断点,这是堆栈跟踪:

#0  0x000000010003bf5a in -[GEElement initWithEntity:insertIntoManagedObjectContext:] at /.../DataModel/Human/GEElement.m:27
#1  0x00007fff89166abc in -[NSManagedObject(_NSInternalMethods) _initWithEntity:withID:withHandler:withContext:] ()
#2  0x00007fff8916540e in -[NSManagedObjectContext(_NSInternalAdditions) _retainedObjectWithID:optionalHandler:withInlineStorage:] ()
#3  0x00007fff891be7f6 in -[NSMappedObjectStore executeFetchRequest:withContext:] ()
#4  0x00007fff89154e63 in -[NSPersistentStoreCoordinator executeRequest:withContext:error:] ()
#5  0x00007fff89152c1b in -[NSManagedObjectContext executeFetchRequest:error:] ()
#6  0x000000010000e50c in +[GEDataModelBase findAllObjectsWithPredicate:] at /.../DataModel/GEDataModelBase.m:72
#7  0x00000001000c04da in +[GEElementTypes elementsOfType:] at /.../Helpers/GEElementTypes.m:75
...etc...

编辑:这是 GEElement init 方法,根据要求。第 27 行是第一行。

- (id)initWithEntity:(NSEntityDescription*)entity insertIntoManagedObjectContext:(NSManagedObjectContext*)context

    self = [super initWithEntity:entity insertIntoManagedObjectContext:context];
    if (self)
    
        // ...A bunch of property initializations here...
    
    return self;

如有必要,我可以发布所有属性初始化,但那里并没​​有什么特别之处。

【问题讨论】:

你能用 GEElement 中包含第 27 行的方法更新你的问题吗? 我认为您使用的是 XML 存储? 嘿,平息,我用包含第 27 行(第一个)的 GEElement init 方法更新了我的问题。我正在使用从 JSON 文件加载的内存存储。 【参考方案1】:

好的...所以我终于弄清楚了导致此问题的应用程序发生了什么。

经过一番挖掘,我发现在多次插入问题之前发生了另一个意外行为:我的一堆 GEElements 被释放但没有从 MOC 中删除。我不小心从唯一对它们有强引用的数组中删除了一些对象。所以我通过在创建 MOC 时添加以下内容来解决我的问题:

managedObjectContext.retainsRegisteredObjects = YES;

显然,MOC 没有保留对象并且它们被释放,但是当我尝试运行查询时,它重新创建了丢失的对象......这是预期的行为吗?

【讨论】:

以上是关于核心数据查询在托管对象上下文中插入新对象的主要内容,如果未能解决你的问题,请参考以下文章

初始化托管对象而不插入托管对象上下文时,核心数据对象属性为零

核心数据获取...为啥在将托管对象插入上下文 A 并保存上下文 A 后,不使用上下文 B 获取托管对象?

仅将托管对象上下文的新条目上传到 ios 中的服务器数据库

核心数据:我的托管对象上的托管对象上下文为零

在 Core Data 中插入一个新的托管对象

核心数据重载数据库