1

Mac アプリケーションにソース リスト (iTunes 風) を追加する必要があります。そのために、( Apple の SidebarDemo ) を試します。それは正常に動作します。reloadDataでのメソッドの効果を示すために、このデモにボタンを追加しましたNSOutlineView。画像でわかるように、問題があります (左側はreloadData通話前、右側はreloadData通話後)。バッジが消える、アイコンが変わるなど。

何が問題ですか?reloadDataon の使用を避けるべきNSOutlineViewですか?

OS X 10.8.2、SDK 10.8、および Xcode 4.5.2 を使用しています。

変更した SidebareDemo プロジェクトは、ここからダウンロードできます。

ありがとうございました!

前後...

4

1 に答える 1

1

SidebarDemoサンプルコードは、同じオブジェクトを使用してアウトラインビューの複数の行を表すという間違いを犯します。特に、データソースで使用される基になるデータは次のように作成されます。

_childrenDictionary = [NSMutableDictionary new];
[_childrenDictionary setObject:[NSArray arrayWithObjects:@"ContentView1", @"ContentView2", @"ContentView3", nil] forKey:@"Favorites"];
[_childrenDictionary setObject:[NSArray arrayWithObjects:@"ContentView1", @"ContentView2", @"ContentView3", nil] forKey:@"Content Views"];
[_childrenDictionary setObject:[NSArray arrayWithObjects:@"ContentView2", nil] forKey:@"Mailboxes"];
[_childrenDictionary setObject:[NSArray arrayWithObjects:@"ContentView1", @"ContentView1", @"ContentView1", @"ContentView1", @"ContentView2", nil] forKey:@"A Fourth Group"];

同一の値のNSStringリテラルはコンパイラーによって一意であるため、出現するたび@"ContentView1"にメモリー内の同じオブジェクトを参照します。この結果、内部のコードが-outlineView:viewForTableColumn:item:アイテムの親を検索して、使用するアイコンまたは未読状態を決定すると、すべてのアイテム-[NSOutlineView parentForItem:]に対して1つの親のみが返されます。@"ContentView1"最初のケースでそれがまったく機能するという事実は、実装の偶然のようです。呼び出し-outlineView:viewForTableColumn:item:が行われる順序は、初期ロード時とリロード時でわずかに異なります。

解決策は、一意のオブジェクトを使用して、アウトラインビューの各アイテムを表すことです。これを実現するSidebarDemoサンプルの最も簡単な変更は、各NSString値の可変コピーを作成してから次の場所に格納することです_childrenDictionary

_childrenDictionary = [NSMutableDictionary new];
[_childrenDictionary setObject:[NSArray arrayWithObjects:[@"ContentView1" mutableCopy], [@"ContentView2" mutableCopy], [@"ContentView3" mutableCopy], nil] forKey:@"Favorites"];
[_childrenDictionary setObject:[NSArray arrayWithObjects:[@"ContentView1" mutableCopy], [@"ContentView2" mutableCopy], [@"ContentView3" mutableCopy], nil] forKey:@"Content Views"];
[_childrenDictionary setObject:[NSArray arrayWithObjects:[@"ContentView2" mutableCopy], nil] forKey:@"Mailboxes"];
[_childrenDictionary setObject:[NSArray arrayWithObjects:[@"ContentView1" mutableCopy], [@"ContentView1" mutableCopy], [@"ContentView1" mutableCopy], [@"ContentView1" mutableCopy], [@"ContentView2" mutableCopy], nil] forKey:@"A Fourth Group"];

実際のコードでは、基になるデータオブジェクトが文字列リテラルだけで構成されるのではなく、モデルクラスのインスタンスで構成されるため、この問題に悩まされることはほとんどありません。

于 2013-01-20T22:43:03.607 に答える