4

Foosの配列を持つクラスTestがあります。ivarを直接公開せずにFoosへのアクセスを提供したいと思います。私はこのKVCを準拠させようとしています(KVO準拠への道を開くためでもあります)。私は持っています:

Test.h

@interface Test : NSObject
{
    NSMutableArray *foos;
}

@property (readonly, copy) NSMutableArray *foos;

@end

Test.m

- (id) init
{
    self = [super init];
    if (self != nil)
    {
        foos = [[NSMutableArray array] retain];
    }
    return self;
}

- (NSMutableArray*) foos
{
    return [self mutableArrayValueForKey:@"foos"];
}

- (NSUInteger)countOfFoos
{
    return [foos count];
}

- (id)objectInFoosAtIndex:(NSUInteger)index
{
    return [foos objectAtIndex:index];
}

- (NSArray *)foosAtIndexes:(NSIndexSet *)indexes
{
    return [foos objectsAtIndexes:indexes];
}

- (void)insertObject:(id)key inFoosAtIndex:(NSUInteger)index
{
    [foos insertObject:key atIndex:index];
}

- (void)insertFoos:(NSArray *)foosArray atIndexes:(NSIndexSet *)indexes
{
    [foos insertObjects:foosArray atIndexes:indexes];
}

- (void)removeObjectFromFoosAtIndex:(NSUInteger)index
{
    [foos removeObjectAtIndex:index];
}

- (void)removeFoosAtIndexes:(NSIndexSet *)indexes
{
    [foos removeObjectsAtIndexes:indexes];
}

クライアントがFooを追加しようとすると、これは無限ループに入ります。

Test *test = [[Test alloc] init];
NSMutableArray *foos = test.foos;
[foos addObject:@"adding object"]; // infinite loop here

私は何が間違っているのですか?

4

3 に答える 3

2
- (NSMutableArray*) foos
{
    return [self mutableArrayValueForKey:@"foos"];
}

アクセサは、アクセスされているプロパティの値を取得するためにKVCを使用しないでください。アクセサはKVCよりも値に近いため、KVCはアクセサを通過するという考え方です。

の正しい実装でfoosは、配列のコピー(変更可能またはその他)を返す必要があります。これが私がそれをする方法です:

- (NSArray *) foos
{
    return [[foos copy] autorelease];
}

また、すべてのアクセサーを公開します。配列を変更したり、特定のインデックスの要素にランダムにアクセスしたりする場合は、その方法で行うことができます。アレイに直接アクセスするのではなく、アクセサーを経由するため、安全でカプセル化されています。

コードを作成するときにアクセスするキーがわからない場合を除いて、KVCプロトコルメソッドを自分で使用する理由は実際にはありません。たとえば、nibローダーまたはCocoa Bindingsシステムを作成している場合は、KVCを使用します。

于 2010-02-10T05:55:42.263 に答える
1

問題は、mutableArrayValueForKeyによって返されるプロキシNSMutableArray:が最初に実際の配列を取得する必要があることです。これは、「foos」メソッドを介して行われます。これはプロキシNSMutableArrayを返すものなので、無限ループに入ります。1つの解決策は、別の名前を使用することです。

- (NSMutableArray*) mutableFoos
{
    return [self mutableArrayValueForKey:@"foos"];
}
于 2010-02-09T16:47:27.243 に答える
0

私はこの問題に非常に長い時間を費やし、アクセサーを介してこれを取得したいと考えていました。入ってくる人たちの答えを明確にしたかったのです。これが私がしたことです。

@property (nonatomic,readonly,getter=getTheFoos) NSMutableArray* foos;

その後、明らかに実装されました:

- (NSMutableArray*)getTheFoos {
    return [self mutableArrayValueForKey:@"foos"];
}

ただし、注意する必要がありましたが、getFoosは(文書化されていない)KVCアクセサーのように見えます。これは、getFoosを同じループに送信するためです。

次にKVOに:

Test* test= [[Test alloc] init];
NSObject* obj= [[NSObject alloc] init];
NSMutableArray* arrTheData= test.foos;

[test.foos insertObject:obj atIndex:0];
[arrFoos insertObject:obj atIndex:0];

arrFoosは、更新され、変更された配列(2つのオブジェクトが含まれます)を読み取ることができますが、配列に挿入してもKVOは起動されません。私の冒険のどこかで、mutableArrayValueForKey:からの戻りがNSMutableArray *を返さないのを見ましたが、そのサブクラスが原因である可能性があります。

于 2012-02-19T22:49:02.497 に答える