Core Data实体在方法中返回后缺少其属性

时间:2013-04-05 14:55:02

标签: ios objective-c xcode core-data

我遇到一个问题,我有一个方法应该返回从当前线程的上下文中获取的Core Data实体对象。

当我在DEBUG模式下编译和运行项目时,一切正常,但当应用程序作为RELEASE运行时,会发生奇怪的行为。返回的对象缺少其属性(它们是nil或0)。该应用程序使用ARC来管理内存。

该实现使用NSManagedObject上的类别和类似的方法:

- (id)threadLocalSelf {
    return [self selfInContext:[NSManagedObjectContext threadLocalContext]];
}

- (id)selfInContext:(NSManagedObjectContext *)context {
    NSAssert(context, @"context cannot be nil!");
    if(context == self.managedObjectContext)
        return self;

    NSManagedObjectID *objectID = [self objectID];
    if([objectID isTemporaryID])
        [NSException raise:NSInternalInconsistencyException format:@"objectID cannot be temporary when fetching self in another context!"];

    NSError *error = nil;
    NSManagedObject *_self = [context existingObjectWithID:objectID error:&error];
    if(error)
        [NSException raise:NSInternalInconsistencyException format:@"Failed to fetch self: %@ in context: %@, error: %@", objectID, context, error];

    NSAssert(_self, @"context: %@ does not contain an object with objectID: %@", context, objectID);

    NSLog(@"Returning _self: %@", _self);

    return _self;
}

[NSManaged threadLocalContext]为当前线程创建一个新的NSManagedObjectContext。

这里的问题是当NSLogging出即将返回的对象时,一切似乎都很好。有关该实体的所有属性和信息都是正确的。

但是 - 在退出对象后退出时(如下所示),所有属性都是nil或0.这种行为只发生在RELEASE而不是DEBUG。

Foo * bar = [baz threadLocalSelf];
NSLog(@"Foo object: %@", bar); 

上面的代码导致对象从方法中正确注销,但NSLog之后的属性是空的。虽然ObjectID在两种情况下都是正确的,但对象本身并不是nil。

关于可能导致这个问题的任何想法都很受欢迎。

2 个答案:

答案 0 :(得分:2)

你的线程新上下文在分配和使用后被释放。

- (id)threadLocalSelf {
    return [self selfInContext:[NSManagedObjectContext threadLocalContext]/*released at the end of method*/];
}

答案 1 :(得分:1)

仅在发布版本中看到此行为的原因是因为NSManagedObjectContext被放入调试版本中的自动释放池中,但ARC优化器会在发布版本中立即释放它。您可以通过立即消除自动释放池来在调试版本中复制它:

- (id)threadLocalSelf {
    @autoreleasepool {
        return [self selfInContext:[NSManagedObjectContext threadLocalContext]];
    }
}