1

私は以前、この質問を関連するスレッドにコメントとして投稿し、簡単だと思っていました。そのスレッドはここにあります:

アレイ コントローラ内の特定の項目への Cocoa バインディング

質問は、objective-c とココアを試して学習するために構築しているゲームに関連しています (ここで詳しく説明します)。テキサス ホールデム ポーカーのように考えれば十分です。1 つのサーバーがゲーム情報を保持し、可変数のクライアント (常に複数) からの入力を管理します。ココア バインディングを介して、IB の配列コントローラーを使用して、サーバー上の配列に格納されているゲームの公開情報を各プレイヤーに表示します。テーブル上の 5 枚のカードがサーバー上の NSArray に格納され、各クライアントの NSArrayController の content フィールドにバインドされていると考えてください。

この部分は、魔法のようにうまく機能します。ただし、各プレイヤーは非公開にする必要がある 2 枚のカードを持っています。各クライアントは、その特定のプレーヤーに配られたものに応じて、異なるカードを表示する必要があります。(実際に起こっているのは、プレイヤー オブジェクトの配列にバインドしているためです。

NSArray * thePlayers, 

すべてのカードが同じアレイに格納されていると想像してください)。だから私の質問は、配列コントローラーから単一のオブジェクトへのバインディングをどのように設定するのですか (または、他のコントローラーが必要ですか)? つまり、Players 配列の 1 人のプレーヤーにバインドするにはどうすればよいでしょうか?」

4

4 に答える 4

4

コントローラまたはモデルにプロパティを設定して、その特定のプレーヤーにアクセスし、それにバインドします。配列内の特定のインデックスにあるオブジェクトに直接バインドする方法はありません。

于 2010-01-18T23:32:02.440 に答える
2

特定の配列インデックスにバインドしたい場合は、ラッパー オブジェクトを作成できます。このようなもの。item0などにバインドできますitem1。範囲チェックはなく、配列のサイズを変更すると壊れますが、アイデアは得られます。

インターフェース

@interface MyArrayBinder : NSObject {
    NSMutableArray *array;
}
- (id)initWithMutableArray:(NSMutableArray *)theArray;
- (NSMutableArray *)array;
@end

実装

#include <objc/runtime.h>

static NSInteger _indexFromSelector(SEL sel) {
    return [[NSStringFromSelector(sel) stringByTrimmingCharactersInSet:[NSCharacterSet letterCharacterSet]] integerValue];
}

static void _dynamicSetItem(MyArrayBinder *self, SEL sel, id obj) {
    [self.array replaceObjectAtIndex:_indexFromSelector(sel) withObject:obj];
}

static id _dynamicItem(MyArrayBinder *self, SEL sel)  {
    return [self.array objectAtIndex:_indexFromSelector(sel)];
}

@implementation MyArrayBinder

- (id)initWithMutableArray:(NSMutableArray *)theArray {
    self=[super init];
    if (self) {
        array=theArray;
        for(NSUInteger i=0; i<[array count]; i++) {
            class_addMethod([self class], NSSelectorFromString([NSString stringWithFormat:@"item%lu", i]), (IMP) _dynamicItem, "@@:");  
            class_addMethod([self class], NSSelectorFromString([NSString stringWithFormat:@"setItem%lu:", i]), (IMP) _dynamicSetItem, "v@:@");  
        }       
    }
    return self;
}

- (NSMutableArray *)array {
    return array;
}

@end
于 2011-02-02T14:15:56.297 に答える
1

ただし、各プレイヤーには2枚のカードがあり、非公開にする必要があります。各クライアントは、その特定のプレーヤーに何が配られたかに応じて、異なるカードを表示する必要があります。(実際に起こっているのは、プレーヤーオブジェクトの配列にバインドしているためです…</ p>

クライアントは、それがどのプレーヤーを代表しているかを知っていますよね?インデックスではなく、キーボードに座っているプレーヤーのPlayerオブジェクトへの直接参照が必要です。のようなものMyPlayer *userPlayer;これは、その1人を含むすべてのプレーヤーの配列を保持しているディーラーオブジェクトに追加されます。

そのように説明すると、クライアントコントローラーがユーザーのPlayerオブジェクトを値とするプロパティを持つようになり、バインドが簡単になります。カードビューをuserPlayerクライアントコントローラーのプロパティのカードAとカードBに直接バインドします。 。(これは基本的に、チャックが彼の回答ですでに提案したことであり、他の質問に対するあなたの回答に対する私のコメントで私が提案したことです。)

すべてのカードが同じアレイに格納されていると想像してください)。

なぜ私はそれを想像したいのですか?なぜプレイヤーは自分のカードを別々に所有しないのですか?

OK、それでディーラーはすべてのカード(つまりデッキ)を所有するべきです。プレイヤーが持っているものも共有する必要があります。プレイヤーはディーラーを通じてカードにアクセスしません。各プレイヤーは自分のカードを直接持っている必要があります。

カードでもプレイヤーと同じ間違いをしたようです。あるオブジェクトがインデックスごとの配列を通じて別のオブジェクトを知ることができる/すべきであると考えています。その知識をBindingsで使用したい場合は、できません。また、使用すべきではありません。一方のオブジェクトは、もう一方のオブジェクトを直接知る必要があります。これは正しい解決策であるだけでなく、オブジェクトがお互いを知るための正しい方法です。配列インデックスベースの参照は、メリットがないため、より複雑になります。

于 2010-01-19T06:06:58.710 に答える
0

ニック・ムーアのソリューションに非常に似ています:

特定の配列インデックスにバインドしたい場合は、ラッパー オブジェクトを作成できます。このようなもの。item0、item1 などにバインドできます。範囲チェックはなく、配列のサイズを変更すると壊れますが、アイデアは得られます。

インターフェース

@interface MyArrayBinder : NSObject
@property NSMutableArray *array;
- (id)initWithMutableArray:(NSMutableArray *)theArray;
@end

実装

static NSInteger _indexFromString(NSString *key) {
    return [[key stringByTrimmingCharactersInSet:[NSCharacterSet letterCharacterSet]] integerValue];
}

@implementation MyArrayBinder

- (id)initWithMutableArray:(NSMutableArray *)theArray {
    if ( self=[super init] ) {
        _array=theArray;
    }
    return self;
}

- (id)valueForUndefinedKey:(NSString *)key {
    return _array[_indexFromString( key )];
}

- (void)setValue:(id)value forUndefinedKey:(NSString *)key {
    _array[_indexFromString( key )] = value;
}

@end
于 2022-02-12T13:28:04.977 に答える