web-dev-qa-db-ja.com

NSMutableArray addObject:-[__ NSArrayI addObject:]:インスタンスに送信された認識されないセレクター

私は日曜日からNSMutableArrayを100の方法で初期化しようとしましたが、NOTHINGは私のために働いています。新しく割り当てられ初期化されたNSMutableArrayと等しく設定し、変数を割り当て、初期化し、考えられるすべての組み合わせと常に同じ結果を得るようにしました。

コードは次のとおりです。

Object.h

NSMutableArray *array;

@property (copy) NSMutableArray *array;

Object.m

@synthesize array;

if ( self.array ) {
    [self.array addObject:anObject];
}
else {
    self.array = [NSMutableArray arrayWithObjects:anObject, nil];
}

注:デバッグでは、「anObject」は実行時にゼロではありません...

AnObjectをテストしましたが、初期化は正常に動作しますが、self.arrayにaddObject:を追加しようとすると、以下のエラーが表示され続けます。

2010-07-10 11:52:55.499 MyApp [4347:1807]-[__ NSArrayI addObject:]:認識されないセレクターがインスタンス0x184480に送信されました

2010-07-10 11:52:55.508 MyApp [4347:1807] ***キャッチされない例外 'NSInvalidArgumentException'によるアプリの終了、理由: '-[__ NSArrayI addObject:]:認識されないセレクターがインスタンス0x184480に送信されました'

何が間違っているのか誰にも分かりますか?

67
Zak

Georg Fritzscheに私の帽子を傾けたいです。私は結局、(保持)の代わりに(コピー)を使用する必要があり、彼の入力なしでは何をすべきかわかりませんでした。

//@property (copy) NSMutableArray *array;
@property (nonatomic, copy) NSMutableArray *array; //overridden method is non-atomic as it is coded and should be reflected here.

可変オブジェクトで(コピー)を使用する場合は、次のように「setter」メソッドをオーバーライドする必要があります...

- (void)setArray:(NSArray *)newArray {

    if ( array != newArray ) { 
        [array release];
        array = [newArray mutableCopy];
//      [array retain]; // unnecessary as noted by Georg Fritzsche
    }

    return;
}

注:コンパイラーの警告が表示されます:「struct NSArray *」を初期化する互換性のないObjective-C型、「struct NSMutableArray *」が期待される配列が渡され、(NSMutableArray *)変数に正しくコピーされました。 newArrayパラメーターを(NSMutableArray *)として宣言する場合は、望ましい結果を得るためにmutableCopyメソッドをそのままにしておく必要があります。

ゲオルグに乾杯! Z @ K!

11
Zak

@property (copy)の合成されたセッターは、配列にcopyメッセージを送信し、不変のコピーを作成します。

Objective-Cガイドの 詳細 のように、ここにセッターを実装する以外に選択肢はありません。

83
Georg Fritzsche

私は自分の投稿を読んでいる証拠だったので、私に考えが起こり、自分の質問に答えました。この解決策はあいまいだったので、先に進み、投稿を作成して自分で回答することにしました(私のような他の初心者はハングアップしません)。

私の間違いは...

@property (copy) NSMutableArray *array;

あるべきだった...

@property (retain) NSMutableArray *array;

エラーはコードの実行方法ではなく、anObjectがNSMutableArray配列を「コピー」しようとした方法では発生していませんでした。

みんな知っているように...

mutableArray = [mutableArray copy];

常に(または私の経験では)等しいとは限りません...

mutableArray = [mutableArray mutableCopy];

そして、これが私の問題の原因でした。 @propertyを(コピー)から(保持)に切り替えるだけで、問題が解決しました。

73
Zak

プロパティが強力で(ARCを使用)、NSMutableArrayで配列を割り当てたにもかかわらず、同じエラーが発生していました。

起こっていたことは、将来の使用のために可変配列(カスタムオブジェクトを含む)をアーカイブし、それをデコードするときに不変のコピーを返すことでした。

誰でも役立つことを願っています。

3
olivaresF

いくつかのインデックスを(他のデータ配列に)持っていて、(適切な理由で)番号順に並べたい。最後にmutableCopyが追加されるまでクラッシュします。 Objective-Cリテラル@ []が変更不可能な配列を返すを思い出すまで、まったく困惑していました。

NSMutableArray *a = [@[@(self.indexA), @(self.indexB)] mutableCopy];
NSLog(@"%@", a);
[indexArray sortUsingComparator: ^(NSNumber *obj1, NSNumber *obj2) {
    return [obj1 compare:obj2];
}];
NSLog(@"%@", a);

ありがとう、ザック!

3
JOM

私は自分が作ったタイプミスのためにこの例外に噛まれました。たぶんそれは誰かを5分救うでしょう。彼らの時間の:

私が書いた:

NSMutableArray *names = [NSArray array];

の代わりに:

NSMutableArray *names = [NSMutableArray array];

NSMutableArrayはNSArrayでもあるため、コンパイラはこれに問題はありませんが、オブジェクトを追加しようとするとクラッシュします。

0
marmor

NSMutable配列のインスタンスに認識されないセレクターが送信されたという同様のエラーがありました。多くのことを経験した後、私は可変配列をプロパティとして使用していることがわかりました

@property (assign, nonatomic) NSMutableArray *myMutableArray;

コピー貼り付けで注意を払っていないと、問題が発生していました。

解決策として、強い型に変更しました(要件に応じて、強い/弱いなど、他の型に変更できます)。だから私の場合の解決策は:

@property (strong, nonatomic) NSMutableArray *myMutableArray;

そのため、コピーの貼り付けには注意してください!一度確認してください。

0
Priyanka

NSArrayオブジェクトを実際に指しているNSMutableArray型にオブジェクトを追加しようとした結果、エラーが発生しました。このタイプのシナリオは、以下のデモコードに示されています。

NSString *test = @"test";
NSMutableArray *mutableArray = [[NSMutableArray alloc] init];
[mutableArray addObject:test];
NSArray *immutableArray = [[NSArray alloc] init];
mutableArray = immutableArray;
[mutableArray addObject:test]; // Exception: unrecognized selector

上記のコードから、サブクラスタイプがスーパークラスタイプに割り当てられていることが簡単にわかります。たとえばJavaでは、これはすぐにエラー(タイプ間の変換エラー)としてフラグが立てられ、問題はかなり迅速に解決されました。 Objective-Cに公平を期すために、互換性のない割り当てを実行しようとすると警告が表示されますが、これだけでは不十分な場合があり、その結果は開発者にとって大きな苦痛になります。幸いなことに、今回は、この痛みのほとんどを負ったのは自分ではありませんでした:P

0
Baljeet Singh