1

iPhone アプリのコア データ プロパティのカスタム アクセサー メソッドに問題があります。プリミティブ型を取り出して返すだけではありません。可能性のある activityTypes の NSSet があり、オブジェクトの PrimitiveType がない場合は、そのセットを調べて、クラスの別の変数に一致する activityType を返します。

以下は、これを行うために思いついたコードです。コードの問題は、への呼び出しが[self willChangeValueForKey:@"type"]無限ループにつながり、プログラムが NSLog を吐き出し続けることです。「型を ... に設定しています」-おそらく、アクセサー内から willChange を呼び出しているためですか?

を取り出して[self willChangeValueForKey:@"type"]もループは発生せず、プログラムは正常に実行され、次にオブジェクトの型にアクセスしようとすると、プリミティブ型が正しく呼び出されます。ただし、ManagedObjectContext に保存する時間になったことを伝えると、どのオブジェクトにも変更がないことがわかります。したがって、willChangeValueForKey を呼び出していないため、primitiveType への変更はオブジェクトに対して永続化されません。

- (ActivityType *)type {

[self willAccessValueForKey:@"type"];
ActivityType *myType = [self primitiveType];
[self didAccessValueForKey:@"type"];

if (myType != nil) {
    NSLog(@"Use primitive (%@)", [myType myDescription]);

} else {

    // 1) find type
    NSSet *types = self.myActivityTypes;

    NSSet *foundTypes = [types objectsPassingTest:^BOOL(id obj, BOOL *stop) {
        ActivityType *object = (ActivityType *) obj;

        return ([object.typeName isEqualToString:self.activityTypeName]);

    }];

    myType = [foundTypes allObjects][0];

    NSLog(@"Setting type to %@", [myType myDescription]);

    // in this case we should not alert anyone since we are inside the getter?
    [self willChangeValueForKey:@"type"];
    [self setPrimitiveType:myType];
    [self didChangeValueForKey:@"type"];


}

return myType;

}
4

2 に答える 2

1

管理対象オブジェクトのプロパティ監視メカニズムは、アクセサーを使用して新しい値と古い値をチェックします。ゲッター内で値を変更しているため、ゲッターが再度呼び出されるため、無限ループが始まります。

この種の遅延読み込みは、管理対象オブジェクトでは実際には機能しません。awakeFromFetch などの別の場所で、または activityTypeName が設定されているときにアクティビティ タイプを設定するか、それが適切でない場合は別のアクセサーを実装できます。

-(ActivityType*)calculatedActivityType
{
    ActivityType *myType = self.activityType;
    if (myType) return myType;

    NSSet *types = self.myActivityTypes;

    NSSet *foundTypes = [types objectsPassingTest:^BOOL(id obj, BOOL *stop) {
        ActivityType *object = (ActivityType *) obj;

        return ([object.typeName isEqualToString:self.activityTypeName]);

    }];

    myType = [foundTypes allObjects][0];
    self.activityType = myType;
    return myType;
}

どのアクセサーにも含まれていないため、これによってループが発生することはありません。

于 2013-01-04T18:58:46.553 に答える
0

別の解決策は、基になる値の型を変更せずに、アクセサーによって新しい型を返すことです。そして...現在のキューで非同期に変更をディスパッチします。

dispatch_async(dispatch_get_current_queue(), ^{
    [self willChangeValueForKey:@"type"];
    [self setPrimitiveType:myType];
    [self didChangeValueForKey:@"type"];
});

完璧ではありません。これにより、「検索コード」が数回実行される可能性があると想像できます。

于 2013-01-24T17:26:00.443 に答える