4

したがって、などで文字列を頻繁に操作する予定がある場合は、stringByAppendingStringNSMutableString型の変数を使用する必要があると確信しています。

しかし、私がこのようなことをしている場合はどうなりますか?

UILabel *someLabel = [[UILabel alloc] init];
[someLabel setText: [[someDictionary objectForKey:@"some_key"] stringByAppendingString:@"some other string"];

NSStringで使用すると、最初のNSStringに関連付けられたポインターが移動し、追加によって作成された新しい文字列を指すため、リークが発生することを読みstringByAppendingStringました。一方、NSMutableStringでは、ポインターは常にその可変文字列を指します。

stringByAppendingStringだから私の質問は、文字列であるが明示的にNSStringまたはNSMutableStringではないものを呼び出すと、暗黙的に何が起こっているのかということです。上記の場合、辞書のキーの値などです。これは間違っていますか?以下のようなことをする必要がありますか?

[[[NSMutableString stringWithString:[someDictionary objectForKey:@"some_key"]] stringByAppendingString:@"some other string"]]
4

4 に答える 4

5

NSStringでstringByAppendingStringを使用すると、最初のNSStringに関連付けられたポインターが移動し、追加によって作成された新しい文字列を指すため、リークが発生することを読みました。一方、NSMutableStringでは、ポインターは常にその可変文字列を指します。

これは、メモリ管理で何が起こっているのかを完全に把握していない人のアドバイスのように聞こえます。確かに[NSString stringByAppendingString]、新しい文字列を返します。しかし、その新しい文字列で何をするかはあなた次第です。次のように、不注意な方法で結果を保持されたプロパティに再割り当てすることで、メモリリークを確実に引き起こす可能性があります。

myStringProperty = [myStringProperty stringByAppendingString:@" more bits"];

正しい形式は、次のように自己を使用することです。

self.myStringProperty = [myStringProperty stringByAppendingString:@" more bits"];

カカオの記憶に関するガイドラインに従ってください。

辞書やその他のコレクションの種類については、辞書から出てくるものを、自分が知っている種類に応じて適切に扱います。実際にはNSStringであるオブジェクトを引き出し、それをNSMutableStringとして使用しようとすると、アプリはフォールオーバーします(「セレクターが見つかりません」など)。したがって、その場合は、NSStringから新しいNSMutableStringを作成する必要があります。

興味深いメモ:AppleはNSMutableStringをNSStringのサブクラスにすることを選択しました。それについての何かは私には賢明ではないように思えます-何かが不変に見える場合、それはタイプNSStringを持っているので、私はそれを不変にしたいです!(しかし、実際にはNSMutableStringである可能性があります。)これを、Stringクラスと完全に別個のBufferedStringクラスを持つJavaと比較してください。

于 2011-03-04T17:01:53.847 に答える
3

私はいつもファンでし[NSString stringWithFormat@"%@%@", a, b];た。なぜなら、あなたは明らかに新しい自動リリースされた文字列を取得し、「a」と「b」を正しく処理できるからです。

を使用[someDictionary objectForKey:@"some_key"]すると、元々そのディクショナリに配置されたオブジェクトのタイプを取得できます。stringByAppendingStringそのため、その辞書の内容を知らずに盲目的に電話をかけるのは悪い考えのようです。

于 2011-03-04T17:01:03.083 に答える
3

-stringByAppendingStringは、関連する両方の文字列とは異なる新しいNSStringを返します。言い換えると:

NSString *string3 = [string1 stringByAppendingString:string2];

string3はまったく新しい文字列です。string1はまったく変更されず、メモリの場所や内容には何も起こりません。おそらく何が起こっているのか誤解しているとあなたに言った人。

[mutableString1 appendString:string2];

この場合、mutableString1は引き続き同じオブジェクトを指しますが、そのオブジェクトの内容はstring2を含むように変更されています。

最後に覚えておくべきことは、可変文字列を使用している場合は、その文字列への参照を共有することに注意する必要があるということです。可変文字列へのポインタを保持する関数に可変文字列を渡し、コードが将来のある時点でその可変文字列を変更した場合、他の参照はまったく同じオブジェクトを指しているため、他のコードは同様に変更します。それがあなたが望むものなら素晴らしいですが、そうでなければあなたは注意しなければなりません。

この問題を回避するための1つの方法は、NSStringの@propertyステートメントを「retain」ではなく「copy」として宣言することです。これにより、プロパティに設定する前に可変文字列のコピーが作成され、-copyメソッドは暗黙的に非可変バージョンを提供するため、NSMutableStringのNSStringコピーが作成されます。

于 2011-03-04T18:00:10.033 に答える
0

メモリ管理のルールに従う場合は、stringByAppendingStringを使用しても問題ありません。一言で言えば:

  1. オブジェクトを所有している場合は、ある時点でオブジェクトを解放または自動解放する必要があります。
  2. alloc、new、またはcopyメソッドを使用してオブジェクトを作成する場合、またはオブジェクトを保持する場合は、オブジェクトを所有します。

Appleのメモリ管理ルールを必ず読んでください。

質問の最初のコードサンプルでは、​​関連するNSStringのalloc、new、copy、retainを使用していないため、リリースするために何もする必要はありません。NSStringでalloc、new、copy、retainを使用しているサンプルに含まれているコード以外の場合は、後でリリースされることを確認する必要があります。

于 2011-03-04T17:05:00.467 に答える