1

私はcocos2d-iphoneを使用してゲームを書いていますが、ステージは.plistファイルで定義されています。ただし、ファイルは大きくなっています。そのため、プロセスに構造を追加し、plistのほとんどを固定フィールドに分割するエディターを開発しました。ただし、一部の要素には引き続きplistエディタータイプの機能が必要なため、「その他のパラメーター」を表示するパネルにNSOutlineViewを実装しました。XCodeの「プロパティリストエディタ」から機能を複製しようとしています。

私は次のシステムを実装しました。http://www.stupendous.net/archives/2009/01/11/nsoutlineview-example/

これは私が必要としているものに非常に近いですが、私が今日のほとんどを解決しようとして費やしてきた問題があります。キー列の値は、親ディクショナリを検索して使用することにより、選択したアイテムから「逆方向」に計算されます。

return [[parentObject allKeysForObject:item] objectAtIndex:0];

ただし、ツリー内の特定のディクショナリ内に同じ値を持つ複数のアイテムがある場合、このステートメントは常にその値を持つ最初のアイテムを返します(isEqualToString:またはハッシュ値を使用して文字列を比較しているように見えます)。これにより、item1、item2、item3の代わりに'item1、item1、item1'を示すキー列が表示されます(項目1〜3はすべて値''を持ちます)。次に試しました。

-(NSString*)keyFromDictionary:(NSDictionary*)dict forItem:(id)item
{
for( uint i = 0; i < [[dict allKeys] count]; i++ ) {
    id object = [dict objectForKey:[[dict allKeys] objectAtIndex:i]];

    if ( &object == &item ) {
        return [[dict allKeys] objectAtIndex:i];
    }
}   

return nil;
}

ただし、これは常にnilを返します。NSOutlineViewの経験が少し多い人が、より良いソリューションを提供できるかもしれないと期待していました。この問題はリンクされた例では1回しか発生しませんが、たとえば辞書からアイテムを削除する場合は、これを何度も使用する必要がありました。どんな助けでも大歓迎です。

4

2 に答える 2

1
return [[parentObject allKeysForObject:item] objectAtIndex:0];

ただし、ツリー内の特定のディクショナリ内に同じ値を持つアイテムが複数ある場合、このステートメントは常にその値を持つ最初のアイテムを返します...</p>

まあ、そうだろう。それがあなたがそれをするように言ったことです:「この値のすべてのキーを取得してください。配列の最初の項目を取得します。それを返す」。

… このステートメントは、常にその値を持つ最初の項目を返します (isEqualToString: またはハッシュ値を使用して文字列を比較しているように見えます)。

それを行っているのはそのステートメントではありません。これが辞書の仕組みです: 各キーは辞書に一度しか入れられず、その値としてオブジェクトを 1 つだけ持つことができます。これは、キーのハッシュを使用し、キーisEqual:メッセージを送信することによって強制されます (NSString 固有の —isEqualToString:キーは文字列である必要はありません*)。

一方、値は一意ではありません。任意の数のキーが同じ値を持つことができます。そのため、値からキー、特にキーへ移行が非常に問題になります。

* とにかく、NSDictionary にはありません。plist 出力を生成しようとすると、ディクショナリに文字列以外のキーが含まれていると barf が発生します。

次に試しました。

-(NSString*)keyFromDictionary:(NSDictionary*)dict forItem:(id)item
{
    for( uint i = 0; i < [[dict allKeys] count]; i++ ) {
        id object = [dict objectForKey:[[dict allKeys] objectAtIndex:i]];

        if ( &object == &item ) {
            return [[dict allKeys] objectAtIndex:i];
        }
    }   

    return nil;
}

しかし、これは常に nil を返します。

それはそのコードの問題の最小のものです。

まず、NSArray を反復処理するときは、絶対に必要でない限り、通常はインデックスを使用しないでください。高速な列挙を使用する方がはるかにクリーンです。

次に、NSArray へのインデックスが必要な場合、正しい型はNSUIntegerです。あなたがそれを助けることができるとき、タイプを混ぜ合わせないでください。

第三に、あなたがそこにある address-of 演算子で何をするつもりだったのかわかりませんが、実際に行ったことは、これら 2 つの変数のアドレスを取得することでした。したがって、ローカル変数objectが引数 variable と同じ変数であるかどうかを比較しましたitem。それらは同じ変数ではないため、そのテストは常に false を返します。これが、オブジェクトを返さない理由です。他の唯一の出口点はnilを返します。これが常に起こることです。

このコードと以前のワンライナーの問題は、値から単一のキーに移動しようとしていることです。これは、辞書の動作に反しています。キーだけが一意です。任意の数のキーが同じ値を持つことができます。

アイテムとして別のものを使用する必要があります。キーをアイテムとして使用するのも 1 つの方法です。各行を表すモデル オブジェクトを作成するのは別の方法です。

モデル オブジェクト ルートを使用する場合は、同じ仮想ディクショナリ内の複数の行が同じキーを持たないようにすることを忘れないでください。NSMutableSet に加えて実装hashし、それisEqual:を支援します。

おそらく、配列の扱いにも同じ変更を加える必要があります。

于 2010-10-22T16:13:03.190 に答える
0

明確にするために、plist ファイル内の各コレクション (つまり、すべての NSMutableArray または NSMutableDictionary) に対してプロキシ オブジェクトを作成することで、最終的にこの問題を解決しました。これは、基本的に Plist 構造をミラーリングし、各レベルで元のオブジェクトへの参照を含めることを意味しました。これにより、各オブジェクトまたはディクショナリ キーの配列インデックスを格納できるようになったため、アイテムをアウトライン ビューから Plist 構造に保存し直すときに、プロキシ オブジェクトで「キー」または「インデックス」プロパティを使用しました。

于 2010-11-02T11:44:42.367 に答える