У меня есть подкласс NSView, у которого есть свойство, которое я хочу привязать. В подклассе я реализовал следующее:
myView.h:
@property (readwrite, retain) NSArray *representedObjects;
myView.m:
@synthesize representedObjects;
+(void)initialize
{
[self exposeBinding: @"representedObjects"];
}
-(void)bind:(NSString *)binding toObject:(id)observableController withKeyPath:(NSString *)keyPath options:(NSDictionary *)options
{
if ([binding isEqualToString:@"representedObjects"]) {
[observableController addObserver: self forKeyPath:@"arrangedObjects" options:NSKeyValueChangeNewKey context:nil];
} else {
[super bind: binding toObject:observableController withKeyPath:keyPath options: options];
}
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
if ([keyPath isEqualToString:@"arrangedObjects"]) {
[self setRepresentedObjects: [object arrangedObjects]];
}
}
Затем я создаю привязку к массиву ControlCler в -[AppController awakeFromNib]
:
[myView bind:@"representedObjects" toObject:arrayController withKeyPath:@"arrangedObjects" options: nil];
Это правильный способ реализации связывания? В нем много кода, который заставляет меня думать, что я делаю что-то не так.
Я думал, что NSObject будет автоматически реализовывать то, что я сделал вручную в -bind:toObject:withKeyPath:options:
, но, похоже, это не так. Если я закомментирую мой -bind:toObject:withKeyPath:options:
, метод setRepresentedObjects никогда не будет вызван.
Дополнительная информация:
Я провел еще несколько расследований и пришел к выводу, что мой первоначальный подход верен, и вам нужно переиграть -bind:toObject:withKeyPath:options:
. Вот цитата из Темы программирования привязок Какао: Как работают привязки? :
В привязке: toObject: withKeyPath: options: метод объект должен как минимум сделать следующее:
- Определите, какая привязка устанавливается
- Запишите, к какому объекту он привязан, с помощью какой траектории и с какими параметрами
- Зарегистрировать в качестве наблюдателя путь к ключу объекта, с которым он связан, чтобы получать уведомления об изменениях
Пример кода в листинге 2 демонстрирует частичную реализацию привязки джойстика: toObject: withKeyPath: options: метод, работающий только с привязкой угла.
Листинг 2 Частичная реализация метода bind: toObject: withKeyPath: option для класса Joystick:
static void *AngleBindingContext = (void *)@"JoystickAngle";
- (void)bind:(NSString *)binding
toObject:(id)observableObject
withKeyPath:(NSString *)keyPath
options:(NSDictionary *)options
{
// Observe the observableObject for changes -- note, pass binding identifier
// as the context, so you get that back in observeValueForKeyPath:...
// This way you can easily determine what needs to be updated.
if ([binding isEqualToString:@"angle"])
{
[observableObject addObserver:self
forKeyPath:keyPath
options:0
context:AngleBindingContext];
// Register what object and what keypath are
// associated with this binding
observedObjectForAngle = [observableObject retain];
observedKeyPathForAngle = [keyPath copy];
// Record the value transformer, if there is one
angleValueTransformer = nil;
NSString *vtName = [options objectForKey:@"NSValueTransformerName"];
if (vtName != nil)
{
angleValueTransformer = [NSValueTransformer
valueTransformerForName:vtName];
}
}
// Implementation continues...
Это ясно показывает, что класс Joystick (который является подклассом NSView) должен переопределить -bind:toObject:withKeyPath:options:
.
Я нахожу это удивительным. Я скептически отнесся к такому выводу, так как не нашел других примеров кода, которые делают это. Однако, как говорится в официальной документации Apple, я должен переиграть -bind:toObject:withKeyPath:options:
. Я пришел к выводу, что это правильный подход.
Я был бы очень рад, если бы кто-то мог доказать, что я не прав!