4

我有一个类 Test,它有一个 Foos 数组。我想在不直接暴露 ivar 的情况下提供对 Foos 的访问。我正在尝试使此 KVC 兼容(也为 KVO 兼容铺平道路)。我有:

测试.h

@interface Test : NSObject
{
    NSMutableArray *foos;
}

@property (readonly, copy) NSMutableArray *foos;

@end

测试.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 的那个,所以它进入了一个无限循环。一种解决方案是使用另一个名称:

- (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 访问器,因为这会将它发送到同一个循环中。

然后到 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可以读取更新后的变异数组(其中将包含两个对象),但插入其中不会触发 KVO。在我冒险的某个地方,我看到 mutableArrayValueForKey: 返回的不是 NSMutableArray*,而是它的子类,这可能是它的原因。

于 2012-02-19T22:49:02.497 回答