1

現在のスレッドのコンテキストからフェッチされた 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 ではありません。

何がこの問題を引き起こす可能性があるかについてのアイデアは非常に高く評価されています.

4

2 に答える 2

1

この動作がリリース ビルドでのみ見られる理由はNSManagedObjectContext、 がデバッグ ビルドで自動解放プールに入れられているためですが、リリース ビルドでは ARC オプティマイザがすぐに解放しているためです。自動解放プールをすぐに空にすることで、デバッグ ビルドでこれを再現できます。

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