【问题标题】:Core Data entity lacks its attributes after being returned in a methodCore Data 实体在方法中返回后缺少其属性
【发布时间】:2013-04-05 14:55:01
【问题描述】:

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

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

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

【问题讨论】:

    标签: ios objective-c xcode core-data


    【解决方案1】:

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

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

    【讨论】:

    • 谢谢!你刚刚拯救了我的一天。
    • 没问题,很高兴为您提供帮助:)
    【解决方案2】:

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

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

    【讨论】:

    • 感谢您解释 DEBUG/RELEASE 的区别!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-09
    • 2018-11-25
    • 2021-07-06
    • 1970-01-01
    • 2022-12-11
    • 2014-08-02
    相关资源
    最近更新 更多