2
votes

First off: I have read questions related to this problem a few times on here and I am posting this with the awareness that people might consider this a duplicate question. But I have to say that as a beginner I have not found any helpful information, so I with this question I hope to make things very clear for me as well as others.

How I understand Bindings & KVC / KVO

Consider this: I have an array (in my AppDelegate), an ArrayController and a view element, say, NSTableView. I have bound the NSMutableArray in my AppDelegate to the ArrayController, which in turn is bound to the NSTableView.

Changing some object's property in the NSTableView leads to an actual change in that object's property. So far it works. However, changing something in the NSMutableArray (e.g. adding an item) does not update NSTableView.

Possible solutions I have read about

I have read multiple answers now. One answer seemed to suggest that I should not add anything to the array itself, but only to the ArrayController. I am not sure if this is correct, but if this is a possible solution it would be great to get a few more details on how to do this.

Other solutions mention the following methods:

  • valueForKey:
  • valueForKeyPath:
  • dictionaryWithValuesForKeys:
  • valueForUndefinedKey:
  • mutableArrayValueForKey:

Especially:

  • mutableArrayValueForKey:

How do I use mutableArrayValueforKey?

What I do not know however is how to use any of these methods with my array / within my application. The mutableArrayValueForKey method returns an NSMutableArray. Do I have to create a new array with this?

Right now, what I am doing is this.

self.vocabList = [[NSMutableArray alloc] init];

and later on, in a method, I am filling the array:

for (NSObject* o in meaningsArray)
{
    NSLog(@"%@",o);

    Vocab *temp = [[Vocab alloc] init];

    [temp setValue:@"w" forKey:@"word"];
    [temp setValue:@"m" forKey:@"meaning"];

    [self.vocabList insertObject:temp atIndex:[self.vocabList count]];
}

If everything I have said is correct so far, my question is: Where would mutableArrayValueForKey: come into the picture when wanting to update the NSTabeleView? Or did I misunderstand something in the first place?

2

2 Answers

1
votes

If you want to change smth in your array and observe the changes, you should make changes in the the mutable Proxy for this array, not in the array itself. mutableArrayValueForKey: return the mutable proxy object.

For example:

I have the array:

NSMutableArray* selectedIndexPaths;

I add the observer:

[self addObserver:self forKeyPath:@"selectedIndexPaths" options:0 context:NULL];

Method for check changes:

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
    if([keyPath isEqualToString:@"selectedIndexPaths"]) {...}}

Methods to change smth in array:

- (void)removeObjectFromSelectedIndexPathsAtIndex:(NSUInteger)index{
    NSMutableArray* arr = [self mutableArrayValueForKey:@"selectedIndexPaths"];
    if (arr) [arr  removeObjectAtIndex:index];
}

- (void) addIndexPathToSelected : (NSIndexPath*) object{
NSMutableArray* arr =[self mutableArrayValueForKey:@"selectedIndexPaths"];
if (arr) {
    [arr addObject:object];
}
}

Use of changers:

- (void)removeAllObjects{
    int count = [selectedIndexPaths count];
    for (int i=count-1;i>-1;i--) {
        [self removeObjectFromSelectedIndexPathsAtIndex:i];
    }
}
0
votes

Easy solution: don't talk to your array, talk to your arraycontroller. Instead of [array addObject:…] do [arrayController addObject:…], instead of [array removeObject:…] do [arrayController removeObject:…] etc.

Solution from CheshireKat:

NSMutableArray *mutableArray = [self mutableArrayValueForKey:@"vocabList"];
for (NSObject* o in meaningsArray)
{
    NSLog(@"%@",o);

    Vocab *temp = [[Vocab alloc] init];

    [temp setValue:@"w" forKey:@"word"];
    [temp setValue:@"m" forKey:@"meaning"];

    [mutableArray insertObject:temp atIndex:[mutableArray count]];
}

Another solution: if you want to entire the whole array, fill an array and set vocabList again.

NSMutableArray *mutableArray = [NSMutableArray array];
for (NSObject* o in meaningsArray)
{
    NSLog(@"%@",o);

    Vocab *temp = [[Vocab alloc] init];

    [temp setValue:@"w" forKey:@"word"];
    [temp setValue:@"m" forKey:@"meaning"];

    [mutableArray addObject:temp];
}
self.vocabList = mutableArray;