NSArrayController and Key Value Coding
I am trying to populate a document based NSTableView
and control it using the NSArrayController
. I g开发者_如何学运维uess I understood the concepts of Key Value coding. However, I fear the NSArrayController
is not honoring the Accessor Search Pattern for Ordered Collections. Let me explain
I have a class Name Student as defined
#import <Cocoa/Cocoa.h>
@interface Student : NSObject {
NSString* studentName;
float marks;
}
//Accessor and mutators
@property (readwrite, copy) NSString* studentName;
@property (readwrite) float marks;
//Initializer - Init all resources
-(id) init;
//Dealloc - Release resources
-(void) dealloc;
@end
The implementation is
#import "Student.h"
@implementation Student
//Synthesize the accessors
@synthesize studentName;
@synthesize marks;
//Initializer - Init all resources
-(id) init
{
self = [super init];
if(self){
studentName = @"New Student";
marks = 0.0;
}
return self;
}
//Dealloc - Release resources
-(void) dealloc
{
[studentName release];
[super dealloc];
}
@end
MyDocument class is defined as follows which contains an NSMutableArray
type instant variable
#import <Cocoa/Cocoa.h>
@class Student;
@interface MyDocument : NSDocument
{
NSMutableArray* students;
}
//Initializers
-(id) init;
//Deallocators
-(void) dealloc;
//Creating the proxy object
-(id) mutableArrayValueForKey:(NSString *)key;
//Array controller uses keyvalue
//coding to call this
-(void) insertObject:(Student*) s inStudentsAtIndex:(int) index;
@end
In IB, the Array Controller's attributes is set to Student object and its instance variables are added to the key. In the binding section, Content Array is bind to File Owner's which is an instance of MyDocument class. The model key path is set to the array name students
Here is the implementation of MyDocument
#import "MyDocument.h"
#import "Student.h"
@implementation MyDocument
- (id)init
{
self = [super init];
if (self) {
students = [[NSMutableArray alloc] init];
}
return self;
}
-(void) dealloc
{
[students release];
[super dealloc];
}
//Array controller uses keyvalue
//coding to call this
-(void) insertObject:(Student*) s inStudentsAtIndex:(int) index
{
NSLog(@"Insert object is called");
}
//Creating the proxy object
-(id) mutableArrayValueForKey:(NSString *)key
{
NSLog(@"Checking if NSArrayController is trying to create a proxy %@",key);
return students;
}
My problem -(void) insertObject:(Student*) s inStudentsAtIndex:(int) index
is never called. However, if I implement a function name -(void) setStudents:(Student*)s
, that is called. -(id) mutableArrayValueForKey:(NSString *)key
is just for debugging purpose; I wanted to see some part of the Key Value coding is working. The behavior is same with or without -(id) mutableArrayValueForKey:(NSString *)key
What am I missing ? I am on Mac 10.6.6 with XCode 3.2.5
Please read the Accessor Search Pattern for Ordered Collections section in here. Quoting the sentence
The receiver's class is searched for a pair of methods whose names match the patterns
-insertObject:in<Key>AtIndex:
and -removeObjectFrom<Key>AtIndex:
(corresponding to the NSMutableArray primitive methodsinsertObject:atIndex:
and removeObjectAtIndex: respectively), or methods matching the pattern-insert<Key>:atIndexes:
and-remove<Key>AtIndexes:
(corresponding to theNSMutableArrayinsertObjects:atIndexes:
andremoveObjectsAtIndexes:
methods).
So you have to implement the PAIR. Your class should implement both -removeObjectFrom<Key>AtIndex:
and insertObject:in<Key>AtIndex:
Based on what you're said, I'm not sure when insertObject:
would be called. In IB, you bound the array controller to your NSMutableArray
, so it doesn't know anything about your MyDocument
class.
If you want some sort of notification of when a new student is added to your array, you would need to hook that up yourself. One way to do this is to handle the action from the UI yourself (such as if you have a New button), and in that handler add the object to your array, and do whatever other logic is required.
精彩评论