NSOutlineView не перерисовывается - PullRequest
0 голосов
/ 04 мая 2010

У меня есть NSOutlineView с флажками. У меня есть состояние флажка привязано к элементу узла с ключом shouldBeCopied. В элементе узла у меня есть методы получения и установки:

-(BOOL)shouldBeCopied {
    if([[self parent] shouldBeCopied])
        return YES;
    return shouldBeCopied;
}

-(void)setShouldBeCopied:(BOOL)value {
    shouldBeCopied = value; 
    if(value && [[self children] count] > 0)
        [[self delegate] reloadData];
}

Идея в том, что если родитель проверен, то и дети должны. У меня проблема в том, что когда я проверяю родителя, он не обновляет это представление детей, если они уже раскрыты. Я могу понять, что это не должно обновляться привязками, потому что я на самом деле не изменяю значение. Но не должно ли reloadData заставить привязки повторно получить значение, вызывая, таким образом, -shouldBeCopied для дочерних элементов? Я пробовал несколько других вещей, таких как -setNeedsDisplay и -reloadItem:nil reloadChildren:YES, но ни одна из них не работает. Я заметил, что дисплей обновляется, когда я переключаюсь на xcode, а затем снова возвращаюсь, и это все, что я хочу, так как мне заставить его так себя вести?

Ответы [ 2 ]

1 голос
/ 07 мая 2010

У меня есть NSOutlineView с флажками. У меня есть состояние флажка привязано к элементу узла с ключом shouldBeCopied.

Вы связываете столбец или ячейку? Вы должны связать столбец.

-(BOOL)shouldBeCopied {
    if([[self parent] shouldBeCopied])
        return YES;
    return shouldBeCopied;
}

Не лучше ли сначала использовать ценность ребенка? Если ничего другого, его дешевле получить (сообщение не требуется).

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

- (BOOL) shouldBeCopied {
     return (shouldBeCopied || [[self parent] shouldBeCopied]);
}

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

Есть два решения. Один чище и будет работать на 10,5 и позже. Другой немного грязный и будет работать на любой версии Mac OS X.

Грязное решение состоит в том, чтобы родительский метод из метода установки отправлял уведомления KVO от имени всех своих дочерних элементов. Что-то вроде:

[children performSelector:@selector(willChangeValueForKey:) withObject:@"shouldBeCopied"];
//Actually change the value here.
[children performSelector:@selector(didChangeValueForKey:) withObject:@"shouldBeCopied"];

Это грязно, потому что один объект публикует уведомления KVO о свойстве другого объекта. Каждый объект должен только утверждать, что знает значения своих собственных свойств; объект, который утверждает, что знает значения свойств другого объекта, рискует быть неправильным, приводя к неправильному и / или неэффективному поведению, не говоря уже о склонности кода вызывать головную боль.

Более чистое решение состоит в том, чтобы каждый объект наблюдал это свойство своего родителя. Передайте параметр NSKeyValueObservingOptionPrior при добавлении себя в качестве наблюдателя, чтобы получить уведомление перед изменением (на которое вы будете реагировать, в метод наблюдения , отправив [self willChangeValueForKey:]) и уведомление после изменения (на которое вы ответите, в методе наблюдения, отправив [self didChangeValueForKey:]).

В чистом решении каждый объект отправляет только уведомления KVO об изменении своего свойства; ни один объект не публикует уведомления о свойствах других объектов.

Возможно, вы захотите, чтобы потомок не отправил себе эти уведомления KVO, когда его собственное значение для свойства равно YES, потому что в этом случае значение родителя не имеет значения. Вы не должны, однако, так как это будет работать только для детей; если у потомка более низкого уровня свойство установлено на NO, тогда значения предков этого объекта имеют значение, и этот объект будет получать уведомление только в том случае, если его отправит каждый из его предков.

1 голос
/ 04 мая 2010

Ваш установщик не отправляет -willChangeValueForKey: и -didChangeValueForKey: до и после изменения, поэтому изменения не будут "замечены" механизмом привязок.

Кроме того, говорить что-либо непосредственно из модельного объекта ... это не очень хороший подход. В этом случае, поскольку вы используете привязки, ваш древовидный контроллер должен записать это изменение (как только вы исправите свой установщик для отправки надлежащих уведомлений) и обновите представление схемы.

...