2009-03-19 4 views
0

私は、クラスloginControllerの実装でNSMutableArrayを作成しました。可変配列には一連の文字列が含まれます。私はそのオブジェクトを持つ変更可能な配列を私のココアプロジェクト内の他のクラスに渡したいと思います。配列を渡す最善の方法は何ですか?NSMutableArrayを他のクラスに渡す

答えて

2

最も基本的なケースは、ログインコントローラがアレイのスナップショットを他のコントローラに渡すだけです。この場合、ログインコントローラは他のクラスのインスタンスへの参照を持つ必要があり、それらのインスタンスのいくつかのプロパティを配列に設定します。 copy属性を持つプロパティを宣言して、受信者が自分の変更可能な配列を保持しないようにしてください。

他のコントローラで配列を変更できるようにしたい場合は、に変更可能な配列を持たせないでください。見つからないバグへの招待です。

代わりに、他の各コントローラの1つのプロパティではなく、ログインコントローラに1つのプロパティを実装する必要があります。ログインコントローラーのプロパティには少なくともゲッ​​ターとセッター(@synthesize)が必要ですが、効率のためにmore specific accessor methodsを実装することができます。

このプロパティを取得したら、他のコントローラはKVOに準拠した方法でプロパティにアクセスする必要があります。特定のアクセサを実装する場合は、それらを使用できます。それ以外の場合は、mutableArrayValueForKey:をログインコントローラに送信する必要があります。そのプロキシ配列の内容にアクセスすると、実際にログインコントローラの配列にアクセスします。プロキシ配列を変更すると、ログインコントローラの配列が順次変更されます。

次は実際のKVOの部分です。他のコントローラーの1人(またはログインコントローラー)がプロパティーを変更したときに、他のコントローラーに知らせたいと思うでしょう。各コントローラ(ログインコントローラを除く)をログインコントローラのプロパティのオブザーバとして追加します。彼らが自分の-dealloc(または-finalize)メソッドで自分自身を削除することを忘れないでください。

正しい通知を送信するためには、すべてアクセサまたはmutableArrayValueForKey:のいずれかを使用する必要があります。これはログインコントローラ自体にも当てはまります。配列を直接メッセージングする代わりに、配列を変更する際には独自のアクセサを使用する必要があります。唯一の例外はinitdeallocです(アクセサーメッセージが半分のメッセージになるため、アクセサーファンシーにしておけば問題になります)。

ところで、あまりにも多くのコントローラーがあるようです。あなたのロジックの一部をモデルオブジェクトに移動することができないかどうかを確認してください。 Cocoaはモデルレイヤーで動作するように設計されているため、コードが大幅に簡素化されます。コントローラーが重いことはフレームワークと戦っているため、より多くの作業ができます。

*「ファンシー」とは、特定のアクセサーメソッドの通常の動作以外に、またはそれに加えて動作することを意味します。たとえば、insertObject:in<Foo>AtIndex:は普通は[<foo> insertObject:atIndex:]を末尾に呼び出します。インスタンス変数の配列以外の場所にオブジェクトを挿入または格納する場合や、同じメソッドで別の操作(表示する必要があるビューを指示する場合など)を行うと、アクセサメソッドが面白くなります。

1
のベストプラクティスではないかもしれない

短い答え:

[otherObject giveArray:[NSArray arrayWithArray:theMutableArray]]; 
0

質問は良いものですが、完全ではない...あなただけの文字列の配列を渡す必要があるか、あるクラスをしてください配列を変更する必要がありますか?

一般に、NSMutableArray *を渡すだけで問題はありませんが、ポインタを渡すだけなので注意する必要があります(したがって、どこかに保持する場合は、所有者いくつかの他のクラスが配列を変更することがあります)。 一般的に、NSMutableArrayを使ってオブジェクトの配列を動的に構築し、それらを共有する必要がある場合は、変更不可能なコピーを作成して渡すことをお勧めします。

NSMutableArray* myArr = [NSMutableArray arrayWithObjects:@"1",@"2",@"3",@"four",nil]; 
// maybe modify the array here... 
NSArray* nonMut = [[myArr copy] autorelease]; 
[someObject doWork:nonMut]; 

| K <

0

私はあなたの状況のた​​めに最善のパターンが委任だと思います。 LoginControllerは、このデータを送信するクラスを知っている必要はありません。あなたが実際に通信するために何かを持っているとき、そして、

@property (nonatomic, assign) id <LoginControllerDelegate> delegate; 

:代わりに、あなたは

@protocol LoginControllerDelegate <NSObject> 

@optional 
- (void)loginController:(LoginController *)loginController didReceiveLoginIDs:(NSArray *)ids; 

@end 

その後LoginControllerDelegateプロトコルを実装して、あなたのLoginControllerクラスでは、このようなdelegateプロパティを実装します代理人の場合は、次のように記述します。

if ([self.delegate respondsToSelector:@selector(loginController:didReceiveLoginIDs:]) 
    [self.delegate loginController:self didReceiveLoginIDs:[NSArray arrayWithArray:loginIDs]]; 

ログインIDを受け取るオブジェクトには、このようプロトコル:

@interface SomeOtherClass : NSObject <LoginControllerDelegate> 

そして、あなたはSomeOtherClassloginController:didReceiveIDs:メソッドを実装します。

このように、LoginControllerでは、プロジェクト内の他のクラスについて詳しく知っている必要はなく、使用可能なオブジェクトがあればそのデータを目的のオブジェクトに送信するためのメカニズムを確立するだけです。どのオブジェクトがログインIDを受け取るべきかを後で変更した場合は、別のデリゲートを選択するだけで済みます。

関連する問題