I have created an NSMutableArray in the implementation of my class loginController. The mutable array contains a set of strings. I want to pass the mutable array with its objects to other classes within my cocoa-project. What is the best way to pass the array?
4 に答える
最も基本的なケースは、ログイン コントローラーが単にアレイのスナップショットを他のコントローラーに渡す場合です。この場合、ログイン コントローラは他のクラスのインスタンスへの参照を持つ必要があり、それらのインスタンスのいくつかのプロパティを配列に設定します。属性を使用してプロパティを宣言することを忘れないでくださいcopy
。これにより、レシーバーがプライベートな可変配列を保持しなくなります。
他のコントローラーが配列を変更できるようにしたい場合は、変更可能な配列を他のコントローラーに持たせないでください。これは、見つけにくいバグへの招待です。
代わりに、他の各コントローラーに 1 つのプロパティを実装するのではなく、ログイン コントローラーに 1 つのプロパティを実装する必要があります。ログイン コントローラのプロパティには、少なくとも getter と setter が必要ですが (これは可能です)、より具体的なアクセサ メソッド@synthesize
を実装して効率化することもできます。
このプロパティを取得したら、他のコントローラは KVO 準拠の方法でプロパティにアクセスする必要があります。特定のアクセサーを実装すると、それらをそのまま使用できます。mutableArrayValueForKey:
それ以外の場合は、ログイン コントローラーに送信する必要があります。そのプロキシ配列の内容にアクセスするとき、実際にはログイン コントローラの配列にアクセスします。プロキシ配列を変更すると、ログイン コントローラの配列も変更されます。
次は実際の KVO 部分です。それらの 1 つ (またはログイン コントローラー) がいつプロパティを変更したかを他のコントローラーに知らせる必要があります。各コントローラー (ログイン コントローラーを除く) を、ログイン コントローラーのプロパティのオブザーバーとして追加します。-dealloc
(または-finalize
) メソッドで自分自身を削除することを忘れないでください。
適切な通知が投稿されるようにするには、すべてでアクセサまたは を使用する必要がありますmutableArrayValueForKey:
。これは、ログイン コントローラー自体にも当てはまります。配列を変更するときは、配列に直接メッセージを送るのではなく、独自のアクセサーを使用する必要があります。唯一の例外はinit
andです (アクセサdealloc
メッセージは半分のオブジェクトへのメッセージであり、アクセサを凝ったものにすると問題になるためです*)。init
dealloc
ところで、コントローラーが多すぎるようです。代わりに、一部のロジックをモデル オブジェクトに移動できないかどうかを確認してください。Cocoa はモデル レイヤーで動作するように設計されているため、コードが大幅に簡素化されます。コントローラーが重いということは、フレームワークとの戦いであり、より多くの作業が必要になります。
*「ファンシー」とは、特定のアクセサー メソッドの通常の動作以外のこと、またはそれに加えて何かを行うことを意味します。たとえば、insertObject:in<Foo>AtIndex:
通常は末尾呼び出しのみ[<foo> insertObject:atIndex:]
です。インスタンス変数の配列以外の場所にオブジェクトを挿入または格納する場合、または同じメソッドで何か他のことを行う場合 (表示する必要があることをビューに伝えるなど)、アクセサー メソッドは空想的です。
ベストプラクティスではないかもしれない短い答え:
[otherObject giveArray:[NSArray arrayWithArray:theMutableArray]];
質問は良いものですが、完全ではありません...文字列の配列を渡すだけですか、それとも渡すクラスで配列を変更する必要がありますか?
一般に、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<
あなたの状況に最適なパターンは委任だと思います。LoginController
このデータの送信先のクラスを知る必要はありません。代わりに、LoginControllerDelegate
プロトコルを実装します
@protocol LoginControllerDelegate <NSObject>
@optional
- (void)loginController:(LoginController *)loginController didReceiveLoginIDs:(NSArray *)ids;
@end
次に、LoginController
クラスで、次のdelegate
ようなプロパティを実装します。
@property (nonatomic, assign) id <LoginControllerDelegate> delegate;
次に、実際にデリゲートに伝えるものがある場合は、次のように記述します。
if ([self.delegate respondsToSelector:@selector(loginController:didReceiveLoginIDs:])
[self.delegate loginController:self didReceiveLoginIDs:[NSArray arrayWithArray:loginIDs]];
ログイン ID を受け取るオブジェクトには、次のLoginControllerDelegate
ようなプロトコルが組み込まれます。
@interface SomeOtherClass : NSObject <LoginControllerDelegate>
そして、loginController:didReceiveIDs:
メソッドを に実装しSomeOtherClass
ます。
LoginController
このように、プロジェクト内の他のクラスに関する詳細な知識を必要とする代わりに、そのデータが利用可能になったときに、関心のあるオブジェクトにそのデータを送信するメカニズムを確立するだけです。ログイン ID を受け取るオブジェクトを後で変更する場合は、別のデリゲートを選択するだけで済みます。