Pertanyaan NSString vs NSMutableString dengan stringByAppendingString


Jadi, saya cukup yakin bahwa jika saya berencana memanipulasi string sering, seperti dengan stringByAppendingString, Saya harus menggunakan variabel tipe NSMutableString.

Tetapi bagaimana jika saya melakukan sesuatu seperti ini?

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

Saya membaca bahwa jika Anda menggunakan stringByAppendingString pada NSString, Anda berakhir dengan kebocoran karena pointer yang terkait dengan NSString awal bergerak, menunjuk ke string baru yang dibuat oleh append, sedangkan dengan NSMutableString, penunjuk Anda selalu menunjuk ke string yang bisa berubah itu.

Jadi pertanyaan saya adalah, apa yang secara implisit terjadi ketika saya menelepon stringByAppendingString pada sesuatu yang merupakan string, tetapi tidak secara eksplisit NSString atau sebuah NSMutableString? Seperti, dalam kasus saya di atas, nilai dari beberapa kunci dalam kamus. Apakah melakukan ini salah, dan haruskah saya melakukan sesuatu seperti di bawah ini?

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

4
2018-03-04 16:46


asal


Jawaban:


Saya selalu menjadi penggemar [NSString stringWithFormat@"%@%@", a, b]; karena kemudian Anda dengan jelas mendapatkan string autoreleased baru dan dapat membuang "a" dan "b" dengan benar.

Dengan [someDictionary objectForKey:@"some_key"], Anda akan mendapatkan jenis objek yang dimasukkan ke dalam kamus itu awalnya. Jadi panggil secara membabi buta stringByAppendingString tanpa pengetahuan tentang apa yang ada di kamus itu sepertinya ide yang buruk.


3
2018-03-04 17:01



Saya membaca bahwa jika Anda menggunakan   stringByAppendingString pada   NSString, Anda berakhir dengan kebocoran   karena penunjuk yang terkait dengan   NSString awal bergerak,   menunjuk ke string baru yang dibuat oleh   append, sedangkan dengan   NSMutableString, penunjuk Anda selalu   menunjukkan string yang bisa berubah.

Kedengarannya seperti saran dari seseorang yang tidak cukup memahami apa yang terjadi dengan manajemen memori. Yakin, [NSString stringByAppendingString] mengembalikan string baru. Tetapi apa yang Anda lakukan dengan string baru itu terserah Anda. Anda pasti bisa menyebabkan kebocoran memori dengan menetapkan kembali hasilnya ke properti yang disimpan dengan cara yang ceroboh, seperti:

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

Formulir yang benar adalah menggunakan diri, seperti:

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

Ikuti panduan memori kakao.

Adapun kamus dan jenis koleksi lainnya: obati apa yang keluar dari kamus dengan tepat sesuai dengan tipe yang Anda ketahui. Jika Anda menarik objek yang sebenarnya adalah NSString, tetapi cobalah menggunakannya sebagai NSMutableString, aplikasi Anda akan jatuh (dengan 'selector not found' atau serupa). Jadi dalam hal ini, Anda perlu membuat NSMutableString baru dari NSString.

Catatan menarik: Apple memilih untuk menjadikan NSMutableString sebagai subkelas dari NSString. Sesuatu tentang hal itu tampaknya tidak bijaksana bagi saya - jika sesuatu terlihat tidak dapat diubah, karena memiliki tipe NSString, saya ingin itu tidak dapat diubah! (Tapi sebenarnya bisa NSMutableString.) Bandingkan dengan Java, yang memiliki kelas String dan kelas BufferedString yang benar-benar terpisah.


5
2018-03-04 17:01



-stringByAppendingString akan mengembalikan NSString baru yang berbeda dari kedua string yang terlibat. Dengan kata lain:

NSString *string3 = [string1 stringByAppendingString:string2];

string3 adalah string yang benar-benar baru. string1 tidak berubah sama sekali, tidak ada yang terjadi pada lokasi memori atau isinya. Orang yang memberitahumu bahwa mungkin hanya salah paham apa yang sedang terjadi.

[mutableString1 appendString:string2];

Dalam hal ini, mutableString1 masih menunjuk pada objek yang sama, tetapi isi objek tersebut telah diubah untuk memasukkan string2.

Satu hal yang perlu diingat adalah bahwa jika Anda menggunakan string yang bisa berubah, Anda harus berhati-hati dengan referensi berbagi untuk itu. Jika Anda meneruskan string yang dapat berubah ke beberapa fungsi yang menyimpan pointer ke string yang dapat berubah itu dan kemudian kode Anda mengubah string yang dapat berubah pada suatu titik di masa mendatang, referensi lainnya menunjuk pada objek yang sama persis yang berarti kode lain akan melihat berubah juga. Jika itu yang Anda inginkan, bagus, tetapi jika tidak Anda harus berhati-hati.

Salah satu cara untuk membantu menghindari masalah ini adalah dengan mendeklarasikan pernyataan @property Anda untuk NSStrings menjadi "copy" alih-alih "retain". Itu akan membuat salinan string Anda yang dapat diubah sebelum menyetelnya di properti Anda dan metode -copy secara implisit memberi Anda versi NON-bisa berubah, sehingga akan membuat salinan NSString dari NSMutableString Anda.


3
2018-03-04 18:00



Jika Anda mengikuti aturan untuk manajemen memori, Anda akan baik-baik saja menggunakan stringByAppendingString. Pendeknya:

  1. jika Anda memiliki objek, Anda harus melepaskan atau melepaskannya secara otomatis pada titik tertentu.
  2. Anda memiliki objek jika Anda menggunakan metode alokasi, baru, atau salinan untuk membuatnya, atau jika Anda mempertahankannya.

Pastikan Anda membaca di Apple Aturan Manajemen Memori.

Dalam contoh kode pertama dalam pertanyaan Anda, Anda tidak menggunakan alokasi, baru, salin atau simpan pada salah satu NSStrings yang terlibat, sehingga Anda tidak perlu melakukan apa pun untuk melepaskannya. Jika di luar kode yang Anda masukkan dalam sampel, Anda menggunakan alokasi, baru, salin, atau simpan di NSString mana pun, Anda perlu memastikan bahwa mereka akan dirilis nanti.


0
2018-03-04 17:05