Reputation: 620
Let me describe my problem first. I have a class which holds a NSMutableDictionary ivar. There is a thread that will add new pairs into this dictionary - at the moment of writing the application I'm not able to have a full list of available keys. An up-to-date list of all this pairs have to be shown in the Table View. I've prepared small proof of concept application where there is a Dictionary Controller created in the xib file, and its content is binded with the dictionary ivar. The problem is that Table View shows only initial set of the dictionary's content. After insertion it's not refreshed.
In my proof of concept application AppController.h is as follows:
#import <Foundation/Foundation.h>
@interface AppController : NSObject
@property (strong) NSMutableDictionary *dictionary;
- (NSString *)randomString;
- (IBAction)addRandomPair:(id)sender;
@end
And the implementation file content:
#import "AppController.h"
@implementation AppController
@synthesize dictionary = _dictionary;
- (id)init {
self = [super init];
if (self) {
_dictionary = [[NSMutableDictionary alloc] init];
[_dictionary setValue:@"Aa" forKey:@"A"];
[_dictionary setValue:@"Bb" forKey:@"B"];
}
return self;
}
- (NSString *)randomString
{
NSMutableString *aString = [[NSMutableString alloc] init];
for (int i = 0; i < 3; i++) {
NSUInteger r = random() % ('z' - 'a');
[aString appendString:[NSString stringWithFormat:@"%c", ('a' +r)]];
}
return aString;
}
- (IBAction)addRandomPair:(id)sender
{
[self.dictionary setValue:[self randomString] forKey:[self randomString]];
NSLog([self.dictionary description]);
}
@end
Dictionary Controller Content is bound to the App Controller with Model Key Path set to "self.dictionary" and columns content in the Table View is bound to Dictionary Controller with Model Key Path set to key and value accordingly. In this proof of concept application button click adds a new pair (addRandomPair: action).
I had a similar problem with a NSMutableArray and Array Controller, but there I was able to solve the problem by adding following pair of methods to the class holding an array ivar (named data in this class):
- (void)insertObject:(NSString *)object inDataAtIndex:(NSUInteger)index;
- (void)removeObjectFromDataAtIndex:(NSUInteger)index;
Is it possible to add some other methods to the class holding a dictionary (AppController) to be notified about new insertions? Or maybe there is a better solution for my problem?
I've found out that implementing following set of accessors makes Dictionary Controller notified about new item:
- (void)addDictionaryObject:(NSString *)object;
- (void)removeDictionaryObject:(NSString *)object;
The problem is that addDictionaryObject:
has only one argument, dictionary would require something like addDictionaryObject:forKey:
. Any ideas?
I don't see any other solution than using manual change notification - in this case addRandomPair:
method looks like this:
- (IBAction)addRandomPair:(id)sender
{
[self willChangeValueForKey:@"dictionary"];
[self.dictionary setValue:[self randomString] forKey:[self randomString]];
[self didChangeValueForKey:@"dictionary"];
NSLog([self.dictionary description]);
}
It works, but I'm still a bit uncertain since dictionary itself will not change, but its content. Is using manual change notification a correct approach here?
Upvotes: 0
Views: 1732
Reputation:
From the Key-Value Coding methods document, only NSMutableArray
or NSMutableSet
is supported for To-Many properties. Since, KVC already works with keys, it would be redundant to have NSMutableDictionary
supported since it's effectively what setValue:forKey:
already does.
Maybe override setValue:forKeyPath:
if you really want this in one call.
Upvotes: 4
Reputation: 4164
You need to call something like
[_tableView reloadData];
That will tell your tableview to essentially refresh everything it knows.
Upvotes: 0