Многоуровневые какао-привязки - PullRequest
2 голосов
/ 12 января 2012

Когда я связываюсь с многоуровневой траекторией, скажем, objectValue.person.photo, она не обновляется при смене человека, а только при смене фотографии. Казалось бы, это проблема только с последним ключом в пути, наблюдаемом для изменений.

Можно ли наблюдать несколько уровней привязок? Например, в SproutCore, если вы поместите звездочку в путь, все после нее будет отслеживаться на предмет изменений (objectValue*person.photo).

1 Ответ

2 голосов
/ 14 января 2012

Если ваши привязки не обновляются при изменении objectValue.person, то это обычно означает, что какой-либо объект в objectValue не соответствует ключу-наблюдению для ключа person. С правильно реализованными объектами, неконечные мутации вдоль keyPath работают нормально. Например, начиная с базового недокументального шаблона приложения какао, я подготовил следующий пример:

Заголовок:

@interface Person : NSObject
@property (copy) NSString* name;
@end

@interface Car : NSObject
@property (retain) Person* driver;
@end

@interface SOAppDelegate : NSObject <NSApplicationDelegate>

@property (assign) IBOutlet NSWindow *window;
@property (retain) Car* car;

- (IBAction)replaceCar:(id)sender;
- (IBAction)replaceDriver:(id)sender;
- (IBAction)changeName:(id)sender;

@end

Реализация:

@implementation Person
@synthesize name;
@end

@implementation Car
@synthesize driver;
@end

@implementation SOAppDelegate
@synthesize car = _car;
@synthesize window = _window;

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
    Person* person = [[[Person alloc] init] autorelease];
    person.name = @"Default Name";
    Car* car = [[[Car alloc] init] autorelease];
    car.driver = person;
    self.car = car;
}

- (IBAction)replaceCar:(id)sender
{
    Person* person = [[[Person alloc] init] autorelease];
    person.name = @"Replaced Car";
    Car* newCar = [[[Car alloc] init] autorelease];
    newCar.driver = person;    
    self.car = newCar;
}

- (IBAction)replaceDriver:(id)sender
{
    Person* person = [[[Person alloc] init] autorelease];
    person.name = @"Replaced Driver";    
    self.car.driver = person;
}

- (IBAction)changeName:(id)sender
{
    self.car.driver.name = @"Changed Name";
}

@end

Затем в .xib я добавил три кнопки, вызывая каждую из IBActions, и добавил метку, свойство value которой было привязано к App Delegate с keyPath car.driver.name

Нажатие на любую из кнопок приведет к обновлению привязанной метки, несмотря на то, что только одна из них на самом деле изменяет точное значение, на которое указывает привязка keyPath (car.driver.name). Соответствие стандарту KVO предоставляется бесплатно со стандартными свойствами @synthesized, поэтому мы получаем правильные обновления независимо от того, с какого уровня в keyPath они поступают.

Короче говоря, привязки работают так, как вы хотите (т.е. они обновляются для изменений ключей не-узловых узлов в составном keyPath). Есть что-то в реализации объектов в objectValue или person, что является недостатком и мешает этому работать. Я бы посмотрел там.

Также обратите внимание, что если одна из этих вещей является коллекцией, то наблюдение за коллекцией - это не то же самое, что наблюдение за всеми объектами в коллекции. См. эту страницу для получения дополнительной информации об этом.

PS: Да, я знаю, что пример утечки памяти. Вы можете представить себе соответствующие -dealloc методы для себя.

...