1

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

当我在调试模式下编译和运行项目时,一切正常,但是当应用程序以 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。

关于可能导致此问题的任何想法都非常受欢迎。

4

2 回答 2

2

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

- (id)threadLocalSelf {
    return [self selfInContext:[NSManagedObjectContext threadLocalContext]/*released at the end of method*/];
}
于 2013-04-05T15:00:08.173 回答
1

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

- (id)threadLocalSelf {
    @autoreleasepool {
        return [self selfInContext:[NSManagedObjectContext threadLocalContext]];
    }
}
于 2013-04-05T15:11:57.730 回答