0

チェックボックス付きの 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て、子を呼び出してはいけませんか? -setNeedsDisplayandなどの他のいくつかのことを試しました-reloadItem:nil reloadChildren:YESが、どれも機能しません。xcode にスワップしてから再び元に戻すと、ディスプレイがリフレッシュされることに気付きました。

4

2 に答える 2

1

チェックボックス付きの NSOutlineView があります。チェックボックスの状態をノード項目にキー shouldBeCopied でバインドしています。

列またはセルをバインドしていますか? 列をバインドする必要があります。

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

子供の値を最初に使用する方がよいのではないでしょうか? 他に何もない場合は、取得する方が安価です (メッセージは不要です)。

修正されたゲッターは次のようになります。

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

私が抱えている問題は、親をチェックすると、子が既に展開されている場合、子のビューが更新されないことです。

解決策は 2 つあります。1 つはよりクリーンで、10.5 以降で動作します。もう 1 つは少し汚れていますが、Mac OS X のどのバージョンでも動作します。

汚い解決策は、setter メソッドから親に、そのすべての子に代わって KVO 通知を投稿させることです。何かのようなもの:

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

これは、別のオブジェクトのプロパティに関する KVO 通知を投稿するオブジェクトがあるため、ダーティです。各オブジェクトは、自身のプロパティの値を知っているとのみ主張する必要があります。別のオブジェクトのプロパティの値を知っていると主張するオブジェクトは、コードが頭痛を誘発する傾向があることは言うまでもなく、間違っているリスクがあり、間違ったおよび/または非効率的な動作につながります。

よりクリーンな解決策は、各オブジェクトにその親のこのプロパティを観察させることです。オブザーバーとして自分自身を追加するときにNSKeyValueObservingOptionPriorオプションを渡して、変更前の通知 ( observation メソッドで を送信して応答し[self willChangeValueForKey:]ます) と変更後の通知 ( で応答します)を取得します。観察方法、送付による[self didChangeValueForKey:])。

クリーン ソリューションでは、各オブジェクトは自身のプロパティの変更に関する KVO 通知のみを送信します。他のオブジェクトのプロパティに関する通知を投稿しているオブジェクトはありません。

プロパティの独自の値が である場合、子がこれらの KVO 通知を自分自身に送信しないようにしたくなるかもしれませんYES。その場合、親の値は問題にならないためです。ただし、これは子供にしか機能しないため、そうすべきではありません。より下の子孫のプロパティが に設定されているNO場合、そのオブジェクトの先祖の値は結局のところ重要であり、その先祖のすべてが投稿した場合にのみ、そのオブジェクトは通知を受け取ります。

于 2010-05-07T02:47:30.740 に答える
1

セッターは、変更の前後に -willChangeValueForKey: および -didChangeValueForKey: を送信しないため、バインディング メカニズムによって変更が「認識」されません。

また、モデルオブジェクトから直接ビューに何かを伝えることは...良いアプローチではありません。この場合、バインディングを使用しているため、ツリー コントローラーは変更を認識し (適切な通知を送信するようにセッターを修正したら)、アウトライン ビューを更新する必要があります。

于 2010-05-04T14:57:19.207 に答える