我遇到一个问题,我有一个方法应该返回从当前线程的上下文中获取的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。
关于可能导致这个问题的任何想法都很受欢迎。
答案 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]];
}
}