On Objective-C/Cocoa Key-Value coding and arrays

北城以北 提交于 2019-12-04 17:29:29

If you want to use KVC properties for an array you should look into the documentation for mutableArrayValueForKey:

Basically with your class:

@interface Bar : NSObject {
    NSMutableArray *items;
}
@end

You would define these methods as a minimum, assuming you initialized your array elsewhere:

- (void)insertObject:(id)object inItemsAtIndex:(NSUInteger)index {
    [items insertObject:object atIndex:index];
}

- (void)removeObjectFromItemsAtIndex:(NSUInteger)index {
    [items removeObjectAtIndex:index];
}

- (NSArray *)items {
    /* depending on how pedantic you want to be
       possibly return [NSArray arrayWithArray:items] */
    return items;
}

Once you've implemented those methods you can call [bar mutableArrayValueForKey:@"items"]. It will return an NSMutableArray proxy object that you can add and remove objects from. That object will in turn generate the appropriate KVO messages and uses the methods you just defined to interact with your actual array.

As Martin suggests, you cannot directly observe an array to see when items are added or removed. Instead, this would be considered a "to-many" attribute of your Bar object, and you would have to deal with making the KVO assertions yourself. You can do something like this for adding and removing items in bar:

@interface Bar : NSObject
{
    NSMutableArray *items;
}
-(void)addItem:(id)item;
-(void)removeItem:(id)item;
@end

@implementation Bar
-(id)init
{
    if( (self = [super init]) ) {
        items = [[NSMutableArray alloc] init];
    }
    return self;
}

-(void)addItem:(id)item
{
    NSParameterAssert(item);
    NSIndexSet *iset = [NSIndexSet indexSetWithIndex:[items count]];
    [self willChange:NSKeyValueChangeInsertion valuesAtIndexes:iset forKey:@"items"];
    [items addObject:item];
    [self didChange:NSKeyValueChangeInsertion valuesAtIndexes:iset forKey:@"items"];
}

-(void)removeItem:(id)item
{
    NSParameterAssert(item);
    NSIndexSet *iset = [NSIndexSet indexSetWithIndex:[items indexForObject:item]];
    [self willChange:NSKeyValueChangeRemoval valuesAtIndexes:iset forKey:@"items"];
    [items removeObject:item];
    [self didChange:NSKeyValueChangeRemoval valuesAtIndexes:iset forKey:@"items"];
}
@end

If you wanted to be able to set/replace items directly, you would have to come up with some way to do that yourself. Normally, I would suggest and NSArrayController for this kind of thing, but since you're using the iPhone, you will have to basically create this functionality yourself.

Well, there's 2 ways you can go about it:

  1. Add an "Add Item" method to your Bar class where you pass in the item
  2. Make sure you're passing in the whole array of items when doing KVC

I don't believe there is a way to add an item to an array using KVC.

It is sufficient to call valueForKey:@"item" and the result will be mutable. So you can say:

NSMutableArray* m = [theBar valueForKey:@"item"];
[item addObject: value];

You don't need those other methods unless you're implementing a facade (a key for which there is not mutable instance variable).

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!