6

*.h ファイルで配列を宣言します。

@interface aViewController: UIViewController
{
   NSMutableArray *anArray; // 後でこれを何度も変更する必要があります。
}
@終わり

*.m ファイルにメモリを割り当てます。

-(無効) viewDidLoad
{
   anArray = [[NSMutableArray alloc] init];
}

テスト ボタンをクリックして配列をロードします (最終的には、クリックするたびに異なる値をロードする必要があります)。

   anArray = [NSMutableArray arrayWithObjects:@"1", @"2", @"3", nil];

そして、私はここでそれを解放します:

-(void) 割り当て解除
{
   [anArray リリース];
   [スーパーdealloc];
}

それはすべて大丈夫に見えますか?

後でこのコードを実行するとクラッシュするため:

   NSLog(@"%d", [anArray カウント]);

単純な「NSLog() とカウント」ですべてがクラッシュする理由がわかりません。


ダーク、

このように言いましょう: 私はポインター、配列、文​​字列、およびメモリについて大きな誤解を持っています。

見つけられるものはすべて読みましたが、(まだ) シンプルで明確でわかりやすい説明を見つける必要があります。

1つ提案できますか?(できれば10ページ未満の読書です。)このトピックだけを説明するリファレンスはありますか...そして「12年のコーディング経験があります...しかし、メモリやポインターの割り当てを扱ったことはありません」という観点から。 )

では、変数名はオブジェクトを参照する方法ではありませんか? では、なぜそれを持っているのですか?

私はこれを行う他の多くの言語に慣れています:

myString = "これ"
myString = "それ"

myInt = 5
myInt = 15

(もっと簡単かもしれません。)


これがこれを行う最も簡単な方法であるように私には見えます。(そして、それは機能しているように見えます。しかし、それは本当に正しいですか?)

最初に NSMutableArray にメモリを割り当てないでください。
メモリを繰り返し再割り当てしないでください。(配列の値を変更したとき。)
繰り返し解放しないでください。(配列の値を変更する前に。)
プログラムを終了するときに解放しないでください。

しかし:
最初に割り当てるときは必ず RETAIN を使用することを忘れないでください
(そして繰り返し再割り当て)新しい値を anArray 変数に。

anArray = [NSMutableArray arrayWithObjects:@"one", @"two", @"three", nil]; で配列をロードしていません。代わりに、それを新しいインスタンスに置き換えています。さらに悪いことに、参照が実際には制御していないエンティティによって所有されているインスタンスに置き換えています。

わお。だから私は 20 の配列を持つことができます.すべて同じ名前: anArray と呼ばれます.それらはすべて異なるでしょうか? (GLOBAL 配列のようなものはありませんか?)

古い値を消去するには、removeAllObject メソッドが便利です。一度に複数の値を追加するために使用できるミューテーションメソッドもあります。

だから...最初に「すべてのオブジェクトを削除する」必要があります...そして、すべての新しい値を再追加する1つのメソッドを呼び出すことができます。

anArray = [[NSMutableArray arrayWithObjects:@"1", @"2", @"3", nil] 保持]; alloc/init シーケンスの代わりに。

わお。スペースを割り当てずに配列に格納することはできないと思いました。

本当に配列全体を置き換えるつもりなら、プロパティの使用を検討することをお勧めします

プロパティを使用してそれを行うにはどうすればよいですか?
このようなことをする正しい方法は何でしょうか:

> anArray = [NSMutableArray arrayWithObjects:@"1", @"2", @"3", nil];
> anArray = [NSMutableArray arrayWithObjects:@"4", @"5", @"6", nil];

私がするように:

x = 12;
x = 24;

わお。文字列、配列、メモリに関するすべてを完全に誤解しています「簡単な方法」は、ONCEを割り当てることだと思いました...可変配列を使用して...必要なだけ変更して...一度解放します。

そうすることの問題は、この新しい配列が保持されないことです。

古い配列はなくなり、新しい配列を使用できると思います。(しかし、そうではないと思います。)

さらに、元の配列を解放していないため、メモリ リークが発生します。

古い配列は解放されるべきではないと思っていました...まだ終わっていません...新しい値を含むように変更したいだけです。(しかし、そうではないと思います。)

しかし、1 つは [anArray release] を使用することです。

私はそれが私が割り当てたメモリを解放する原因になると考えていました...(しかしそうではないと思います)...そして、より多くのメモリを再割り当てする必要があります。(しかし、そうではないと思います。)

anArray = [[NSMutableArray arrayWithObjects:@"1", @"2", @"3", nil] 保持];

それを「保持」しなければならないので、私の下から消えないようにするには?(なぜそうなるのかわからない。最終的なdealloc呼び出しで...に指示するまで。)

別の、おそらくより正しい修正方法は、常に新しい配列を作成する代わりに、addObject: または addObjectsFromArray: NSMutableArray メソッドを使用することです。

私は1つの配列を作成したいだけです...そしてそれを好きなように使用してください。配列に追加したくありません。私はそれを私の新しい価値観に設定したい。

4

3 に答える 3

11

配列をロードしていません

anArray = [NSMutableArray arrayWithObjects:@"one", @"two", @"three", nil];

代わりに、それを新しいインスタンスに置き換えています。さらに悪いことに、参照が実際には制御していないエンティティ (おそらくNSAutoreleasePool.)によって所有されているインスタンスを使用しています。

[[NSMutableArray alloc] init]

失われて漏洩します。

配列参照全体を置き換える代わりに、たとえば次addObject:のように使用して、すでに自由に使用できるものを変更します

[anArray addObject: @"one"]
[anArray addObject: @"two"]

古い値を消去するには、このメソッドremoveAllObjectが便利な場合があります。一度に複数の値を追加するために使用できるミューテーションメソッドもあります。

Alternatively, you can allocate the array using the construction method you already use, but be careful to retain it. In viewDidLoad do

anArray = [[NSMutableArray arrayWithObjects:@"one", @"two", @"three", nil] retain];

instead of the alloc/init sequence.

If you really intend to replace the entire array, you may want to consider using properties instead of doing the reference counting manually.

于 2010-02-22T00:14:34.047 に答える
4

問題はanArray = [NSMutableArray arrayWithObjects:@"one", @"two", @"three", nil];、これが最初に作成した配列を置き換えることです。これを行う際の問題は、この新しい配列が保持されないため、メソッドが戻るとすぐに失われることです。さらに、元の配列を解放していないため、メモリ リークが発生します。

これを修正するにはいくつかの方法がありますが、[anArray release]; anArray = [[NSMutableArray arrayWithObjects:@"one", @"two", @"three", nil] retain];代わりに使用する方法があります。

別の、おそらくより正しい修正方法は、常に新しい配列を作成する代わりに、addObject:またはメソッドを使用することです。addObjectsFromArray: NSMutableArray

于 2010-02-22T00:15:51.797 に答える
3

この単純なメモリ ルールを覚えておいてください:自分が所有するオブジェクトのみを解放します。以下を使用してオブジェクトを作成した場合にのみ、オブジェクトを所有します。

  • init (このメソッドは、保持カウントが 1 の新しいオブジェクトを作成します)
  • new (この方法は alloc と init を使用するのと同じです)
  • copy (このメソッドは、保持カウントが 1 で、メソッドのレシーバーの内容で新しいオブジェクトを作成します)
  • retain (このメソッドは保持カウントを 1 増やします)

システムdeallocは、保持カウントがゼロのオブジェクトを自動的に処理します。所有してreleaseいるすべてのオブジェクトは、使い終わった後でなければなりません。早すぎるreleaseと、危険な状況になります。releaseオブジェクトを使い終わったときにそれを行わないと、リークが発生します。

ポインターは、メモリ内のオブジェクトを参照する特別なオブジェクトです。基本的にはメモリアドレス(およびその他のデータ)です。オブジェクトを使用する場合は、allocメモリを消費してからinitialize する必要があります。=(記号を使用して) ポインターに割り当てます。

string = [[NSString alloc] init];

string保持カウントが 1 になりました。ただし、NSStringは不変オブジェクトであるため、初期化後に変更することはできません。値を割り当てる 1 つの方法stringは、初期化中に行うことです。

string = [[NSString alloc] initWithString: @"Hello, World!"];

定期的に変更する必要がある場合stringは、変更可能な別のクラスを使用できます: NSMutableString. それでも、それらを変更する唯一の方法はメッセージです。

string = [[NSMutableString alloc] initWithString: @"Initial string"];
[string setString: @"Modified string"];

次のコードは間違っているため、メモリ リークが発生することに注意してください。

string = [[NSMutableString alloc] initWithString: @"Initial string"];
string = @"Modified string";

最初の行でstringは、新しく作成されたオブジェクトに割り当てられます。2 番目のものでstringは、別の文字列に割り当てられます。新しく作成されたオブジェクトへの参照が失われ、リークが発生します。参照がないオブジェクトを解放することはできません。

int「ネイティブ」オブジェクトであるため、整数(型)でこれを行う場合、問題は発生しません。Objective-C ランタイムは、これらのデータ型をポインターではなく値に直接関連付けます。

int1 = 4;
int1 = 5;

注 1.常にランタイムにポインタの型を伝えることを忘れないでください。を使用する場合stringは、最初にヘッダー (パブリックの場合) または実装 (他のメソッドから隠したい場合) で定義する必要があります。その後、名前を自由に使用できます。

NSString *string;

星は、それがポインターであることをランタイムに伝えます。ネイティブ型の場合、ポインターがないため、これを取得します。

int int1;

注 2.配列 (および辞書など)NSStringは、不変バリアントと可変バリアントの両方を持つという点で、すべて同じように動作します。

注 3.ほとんどのクラスには、割り当て、初期化、および自動解放を一度に行う特別なメソッドがあります。

NSArray *myArray = [NSArray arrayWithObjects: @"Butter", @"Milk", @"Honey", nil];

release自動解放されたオブジェクトは、システムがreleaseしばらくすると手動で解放するので、手動は必要ありません。オブジェクトの永続的な部分としてではなく、メソッドの実行中またはメソッド間でのみオブジェクトが必要な場合に非常に便利です。autoreleaseメイン スレッド (GUI を備えたアプリ内) でオブジェクトを処理すると、イベント ループが現在のループを終了するとdreleaseになります (イベントが処理されると終了します)。Apple のドキュメントで自動解放プールの詳細を参照してください。

ポインターとは何かをよく理解していないすべての人に役立つことを願っています。私自身、実験を重ねるまでの数か月間、問題を抱えていました。:-)

于 2011-05-15T00:16:56.527 に答える