5

私はこの小さなコードを持っています

 NSMutableArray *myArray = [[NSMutableArray alloc] init]; 
 NSNumber *myNumber = [NSNumber numberWithDouble:752.65];

 [myArray addObject:myNumber];

このコードでは、配列内にオブジェクトを格納します。しかし、今では互いに独立した 2 つのオブジェクトがあります。

配列に追加された後に myNumber を変更しても、配列内の値は変更されません。どうすればそれをアーカイブできますか? 配列のみへのポインタを与えようとしましたが、うまくいきませんでした。

4

4 に答える 4

16

変数を配列に入れることはできません。それmyNumberが変数です。変数はコンテナであり、配列もコンテナです。違いは、変数は配列のようにオブジェクト*でもなく、オブジェクトのみを配列に入れることができることです。

渡すaddObject:のは変数myNumberではなく、含まれるオブジェクトです。それが配列に追加しているものです。

addObject:&myNumber内部のオブジェクトの代わりに変数を追加するには、変数自体へのポインターを渡すために、を実行する必要があります。しかし、次の 2 つの理由から、これは機能しません。

  1. 前述したように、変数はオブジェクトではなく、追加できるのはオブジェクトのみです。
  2. これはローカル変数であるため、関数が終了すると消滅します。次に、配列内のデッドメモリへのポインタがあります。そのポインターにあるものにアクセスしようとすると、プログラムがクラッシュします。

機能する 3 つのソリューションがあります。

  1. f3lix が示唆するように、変更可能な数値クラスを作成し、NSNumber の代わりにこのクラスから数値オブジェクトを作成します。NSNumber のドキュメントで説明されているように、NSValue のすべてのプリミティブ メソッドをオーバーライドする必要があります。
  2. オブジェクトを変更する代わりに、配列内のオブジェクトを置き換えます。もちろん、これには、数値を変更したいすべての場所から配列にアクセスできる必要があります。
  3. 数をプロパティとして持つモデル オブジェクト クラスを作成します。

私の意見では、最後の解決策は正しいものです。数字のリストだけを管理しているとは思えません。多くの場合、プロパティとして数値を持つもののリストをユーザーに表示しています。これをコードでモデル化すると、すべてがはるかに簡単になります。

裸の NSNumbers をモデル オブジェクトに置き換えた後のコードは次のようになります。

MyModelObject *myModelObject = [[[MyModelObject alloc] init] autorelease];
[myModelObject setNumber:[NSNumber numberWithDouble:42.0]];
[myArray addObject:myModelObject];

//Some time later, you decide to change the number.
[[myArray objectAtIndex:idx] setNumber:[NSNumber numberWithDouble:43.0]];
//Or:
for (MyModelObject *obj in myArray) {
    [obj setNumber:1000.0];
}

※Cocoaオブジェクトのことです。C 言語では、ポインター、int などを「オブジェクト」と呼びますが、これは別の定義です。

于 2009-03-30T10:58:01.657 に答える
10

あなたの問題は、 NSNumber オブジェクトが不変であることです。つまり、それらの値を変更することはできません。したがって、値を変更するには、新しい NSNumber オブジェクトを作成する必要があります。例えば:

myNumber = [NSNumber numberWithDouble:[myNumber doubleValue]+1.0]

もちろん、配列に追加したオブジェクトとは異なるオブジェクトを指す myNumber があります。したがって、変更された NSNumber オブジェクトを置き換えて配列を更新する必要があります。

[myArray replaceObjectAtIndex:0 withObject:myNumber]

さて、これにより、配列を更新できるようにするために、各 NSNumber と一緒にインデックスを格納する必要があるという問題が残ります。NSNumber オブジェクトを渡して値を変更できるようにする場合、これは不便です。

この問題は、透過的な更新を可能にするために NSNumber をラップするラッパー オブジェクトを導入することで解決できます。または、doubleValue を処理する独自のクラス (多少変更可能な NSNumber クラス) を作成することもできます。

于 2009-03-30T09:12:57.227 に答える
3

ポインター myNumber を変更しても、あなたが言ったように、配列に格納されている値は変更されません。ただし、配列に格納されているポインターは myNumber のコピーであるため、myNumber が指すオブジェクトを変更すると、配列要素が指すオブジェクトは同じオブジェクトであるため、その変更が反映されます。

あなたがしたいことは、配列が別のオブジェクトを指すようにすることです(myNumberを変更するたびに)。たとえば、次のように -replaceObjectAtIndex:withObject: を使用して、これを手動で行う必要があります。

NSNumber *myNumber = [NSNumber numberWithDouble: 3.141592];
int myNumberIndex = [myArray count];
[myArray addObject: myNumber];

myNumber = ...; //whatever
[myArray replaceObjectAtIndex: myNumberIndex withObject: myNumber];

基本的に、このコードが行うことは、myArray に入れたオブジェクトのインデックスを格納し、そのオブジェクトを新しいオブジェクトに置き換えることです。

于 2009-03-30T09:11:03.363 に答える
2

あなたは次のようなものが欲しいようNSPointerArrayです...

NSPointerArray はおそらく、(これらの) 特殊化されたコレクション クラスの中で最も強力なものの 1 つです。のようなインターフェイスを指定し NSArrayますが、null 値 (および任意のポインター) の挿入を許可します。さらに、 のインスタンスを作成するときに特定のオプションを指定することにより NSPointerArray、アレイに格納されているオブジェクトに関して特定のメモリ管理ポリシーを持つようにアレイを構成できます。

-initWithOptions:メソッドまたはを使用して作成するときに、NSPointerArray のインスタンスのオプションを指定します-initWithPointerFunctions:。メソッド -initWithOptions:` を使用する場合、作成する配列がパラメーターとして渡すオプションによって設定されたポリシーに従うことを指定します。オプションは、ビットごとの OR を使用して指定され、アレイの特定のポリシーまたは「パーソナリティ」を設定します。

そしてそれは続く...

このインスタンスを に渡すNSPointerArrayと、通常の で使用される通常の保持、解放、およびその他のメソッドの代わりに、オブジェクトの挿入、削除などの際に定義した関数が使用されますNSArray

ソース(ただし、詳細を知りたい場合は他の場所を参照してください)

于 2012-09-23T11:34:17.660 に答える