2010-01-25 3 views
2

Вот настройка: У меня есть подкласс IKImageBrowserView, у которого zoomValue свойство привязано к ключу VFBrowserZoomValue в общем NSUserDefaultsController. У меня есть NSSlider, чья привязка value привязана к одному и тому же ключу.Наблюдение NSUserDefaultsController не работает, когда установлены связанные свойства

Это прекрасно работает, чтобы изменить zoomValue браузера с ползунка.

Я пытаюсь реализовать -magnifyWithEvent: в моем подклассе IKImageBrowserView, чтобы можно было масштабировать браузер с помощью жестящего пальца на трекпадах.

Вот моя реализация:

-(void)magnifyWithEvent:(NSEvent *)event 
{ 
    if ([event magnification] > 0) { 
    if ([self zoomValue] < 1) { 
     [self setZoomValue: [self zoomValue] + [event magnification]]; 
    } 
    } 
    else if ([event magnification] < 0) { 
    if ([self zoomValue] + [event magnification] > 0.1) { 
     [self setZoomValue: [self zoomValue] + [event magnification]]; 
    } 
    else { 
     [self setZoomValue: 0.1]; 
    } 
    } 
} 

Это изменяет браузера zoomValue правильно. Проблема в том, что NSUserDefaults не обновляется с новым значением.

В другом месте приложения у меня есть реализация -observeValueForKeyPath:ofObject:change:context:, которая наблюдает за браузера. Если я регистрирую значения масштабирования браузера, значения ползунка и ключа по умолчанию в этом методе, я вижу, что значение масштабирования браузера не было перенесено в NSUserDefaults, и ползунок не обновился.

Я пробовал окружить метод -magnifyWithEvent: с вызовами -{will,did}ChangeValueForKey.

+0

Если вы создаете наблюдателя в zoomValue браузера с NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld как параметры, передается ли словарь изменений для наблюденияValueForKeyPath: ofObject: change: context: содержать правильный NSKeyValueChangeNewKey и NSKeyValueChangeOldKey? – hatfinch

ответ

4

Поток KVO для привязок не является ортогональным; обязательным является не имущество, это ссылка собственности. Это сокращенное помнить о том, как работать привязки:

  • KVO используется для передачи изменений от модели к контроллеру & вида.
  • KVC используется для связи изменений с точки зрения контроллера &.

Таким образом, когда представление с привязками обрабатывает события, оно должно распространять изменения в свойствах, которые ссылаются на его привязку.

Вот что ваш код может выглядеть следующим образом, с помощью метода полезности для выполнения тяжелых распространяющихся изменений через привязки:

- (void)magnifyWithEvent:(NSEvent *)event 
{ 
    if ([event magnification] > 0) { 
    if ([self zoomValue] < 1) { 
     [self setZoomValue: [self zoomValue] + [event magnification]]; 
    } 
    } 
    else if ([event magnification] < 0) { 
    if ([self zoomValue] + [event magnification] > 0.1) { 
     [self setZoomValue: [self zoomValue] + [event magnification]]; 
    } 
    else { 
     [self setZoomValue: 0.1]; 
    } 
    } 

    // Update whatever is bound to our zoom value. 
    [self updateValue:[NSNumber numberWithFloat:[self zoomValue]] 
     forBinding:@"zoomValue"]; 
} 

Это немного жаль, что ImageKit требует использования @"zoomValue" для ссылки на Увеличить значение привязка IKImageBrowserView, большинство привязок в AppKit имеют свою собственную глобальную константу строки, такую ​​как NSContentBinding.

А вот что общий метод утилита для распространения изменений через связывание:

- (void)updateValue:(id)value forBinding:(NSString *)binding 
{ 
    NSDictionary *bindingInfo = [self infoForBinding:binding]; 

    if (bindingInfo) { 
    NSObject *object = [bindingInfo objectForKey:NSObservedObjectKey]; 
    NSString *keyPath = [bindingInfo objectForKey:NSObservedKeyPathKey]; 
    NSDictionary *options = [bindingInfo objectForKey:NSOptionsKey]; 

    // Use options to apply value transformer, placeholder, etc. to value 
    id transformedValue = value; // exercise for the reader 

    // Tell the model or controller object the new value 
    [object setValue:transformedValue forKeyPath:keyPath]; 
    } 
} 

На самом деле, применяющие заполнители, трансформаторы значения, и тому подобное в качестве упражнения для читателя.

0

Я боюсь, что это ожидаемое поведение, см. this FAQ section документации по привязке. Вам нужно нажать это вручную.

0

Когда вы создаете совместимый с привязкой элемент управления (или, в вашем случае, подклассифицируя его), он должен контролировать уведомление, когда его значение изменяется. Итак, что вы хотите сделать, это переопределить

- (void)bind:(NSString *)binding toObject:(id)observableController withKeyPath:(NSString *)keyPath options:(NSDictionary *)options 

и следить за связывание вы заинтересованы. Следите за observableController и keyPath (а также options словарь, если какое-либо значение трансформаторов использоваться). Когда вы обновите значение своего элемента управления, вам необходимо будет отправить

[observableController setValue:newValue forKeyPath:keyPath]; 

, чтобы обновить контроллер с новым значением. Наблюдение за ключевыми знаками - это улица с односторонним движением, а в привязках контроль - это наблюдатели.