Ручная вязка в какао - PullRequest
       10

Ручная вязка в какао

2 голосов
/ 03 апреля 2011

У меня есть ImageView, который показывает блокировку, сообщая, заблокирован ли открытый файл или нет.У меня есть 2 изображения для заблокированных и разблокированных дел.Я хочу синхронизировать отображаемое изображение с логическим значением моего объекта, представляющего открытый файл.

Для этого я хочу, чтобы мой ViewController изменил изображение в моем ImageView в зависимости от состояния блокировки объекта.Таким образом, и object, и ViewController имеют свойство isLocked.

Как их синхронизировать?В IB это легко, но я не знаю, как это сделать программно.Я попытался в методе инициализации моего ViewController использовать:

[ViewController bind:@"value" toObject:[ArrayController selection] withKeyPath:@"isLocked" options:nil];

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

Я пытаюсь поместить следующий код в метод инициализатора моего объекта:

[self exposeBinding:@"isLocked"];

Но Xcode не делаетузнайте этот метод.

Есть ли у кого-то опыт установления такого рода привязок?

Ответы [ 2 ]

6 голосов
/ 04 апреля 2011

Как говорит @nick, вам нужно Key-Value-Observing.

[arrayController addObserver:self 
                forKeyPath:@"selection.isLocked"
                options:NSKeyValueObservingOptionNew
                context:@"this_context"]

Затем, когда isLocked изменяет, -observeValueForKeyPath: ofObject: change: context: метод, который вы добавили в viewController, будет вызываться(при условии, что вы манипулируете только isLocked совместимым способом KVC).

Параметр options позволяет при необходимости настраивать, какие именно условия будут вызывать уведомление, и какие данные отправляются вместе с уведомлением.Параметр context предназначен для того, чтобы вы могли различать уведомления, которые вы зарегистрировали для получения, и уведомления, которые ваш суперкласс зарегистрировал для получения.Это необязательно.

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

Да, многие вещи создают впечатление, что это то, что они делают, и мало кто говорит, что это не так.не то, что они делают, также многие люди считают, что это то, что они делают, но нет, вы не можете использовать их для этого.

Только несколько классов поддерживают привязки ( они перечислены здесь), затем , и это важный бит , эти классы поддерживают только привязку именованных привязок , и эти привязки не являются переменными экземпляра.Например, NSTextField имеет привязку ' fontFamilyName ', но NSTextField не имеет свойства 'fontFamilyName' или переменной экземпляра, даже производной.NSTextField имеет свойство «isBordered», но не привязку, поэтому вы не можете связать «isBordered».

Это ничего не значит для «связывания» произвольного свойства произвольного класса.

1 голос
/ 15 марта 2014

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

#import <Cocoa/Cocoa.h>

@interface SomeObject : NSObject

@property (retain,nonatomic) id someValue;

@end
@implementation SomeObject

@end

int main()
{
   SomeObject *source=[SomeObject new];
   SomeObject *target=[SomeObject new];

   [target bind:@"someValue" toObject:source withKeyPath:@"someValue" options:0];
   [source bind:@"someValue" toObject:target withKeyPath:@"someValue" options:0];

   [source setSomeValue:@(42)];
   NSLog(@"target: %@",[target someValue]);


   [target setSomeValue:@(22)];
   NSLog(@"source: %@",[source someValue]);

  return 0;
}

Насколько я могу судить, проблема в бите [ArrayController selection]. Первая проблема состоит в том, что ArrayController является (или должен быть) классом, и получение выбора класса, вероятно, бессмысленно. Другая проблема заключается в том, что даже если бы это был экземпляр, вы бы привязывались к выбору во время вызова, что почти наверняка не то, что вы хотите. Вы хотите отслеживать текущий выбор по мере его изменения.

Итак, вы хотите что-то вроде следующего:

[myViewController bind:@"value" toObject:myArrayController withKeyPath:@"selection.isLocked" options:nil];
...