@property retain, assign, copy, nonatomic di Objective-C

214

Sebagai seseorang yang baru di Objective-C, bisakah seseorang memberi saya tinjauan umum tentang mempertahankan, menetapkan, menyalin, dan orang lain yang saya lewatkan, yang mengikuti arahan @ properti? Apa yang mereka lakukan dan mengapa saya ingin menggunakan satu sama lain?

Mark Reid
sumber
1
Nama Apple untuk ini adalah "atribut" atau "atribut properti"
nevan king

Jawaban:

273

Artikel yang ditautkan oleh MrMage tidak lagi berfungsi. Jadi, inilah yang saya pelajari dalam coding waktu singkat saya di Objective-C:

nonatomic vs atomic - "atomic" adalah default. Selalu gunakan "nonatomik". Saya tidak tahu mengapa, tetapi buku yang saya baca mengatakan "jarang ada alasan" untuk menggunakan "atom". (BTW: Buku yang saya baca adalah buku BNR "iOS Programming".)

readwrite vs readonly - "readwrite" adalah default. Saat Anda mensintesis, pengambil dan penyetel akan dibuat untuk Anda. Jika Anda menggunakan "readonly", tidak ada setter yang akan dibuat. Gunakan untuk nilai yang tidak ingin Anda ubah setelah instantiasi objek.

simpan vs. salin vs. tetapkan

  • "assign" adalah default. Di setter yang dibuat oleh @synthesize, nilai hanya akan ditugaskan ke atribut. Pemahaman saya adalah bahwa "menetapkan" harus digunakan untuk atribut non-pointer.
  • "retain" diperlukan ketika atribut adalah penunjuk ke objek. Setter yang dihasilkan oleh @synthesize akan mempertahankan (alias menambah jumlah retain) objek. Anda harus melepaskan objek setelah selesai.
  • "copy" diperlukan ketika objek bisa berubah. Gunakan ini jika Anda memerlukan nilai objek seperti saat ini, dan Anda tidak ingin nilai itu mencerminkan perubahan yang dibuat oleh pemilik objek lain. Anda harus melepaskan objek setelah selesai karena Anda menyimpan salinannya.
Blamdarot
sumber
@Blamdarot - apakah saya harus merilisnya dengan ARC juga
Dejell
10
@Odelya - Tidak. Jika Anda melepaskan saat menggunakan ARC, saya yakin Anda akan mendapatkan kesalahan kompiler.
Blamdarot
52
"Selalu gunakan nonatomik" adalah saran yang buruk. Anda harus tahu apa yang Anda menyerah ketika Anda menggunakan nonatomik.
Jesse Rusak
7
Sepakat. Secara khusus, banyak orang tampaknya tidak tahu bahwa nilai-nilai nonatomik tidak dipertahankan-autoreleased oleh pengambil. nonatomik sering sesuai, tetapi pemrograman kultus kargo jarang dilakukan.
Catfish_Man
9
Menyarankan untuk meninggalkan default atomicsama buruknya dengan memberi saran nonatomic. Tidak ada pilihan yang "benar", jadi perancang bahasa memilih yang lebih aman dari dua solusi. Bahkan pada nonatomicumumnya pilihan yang lebih baik karena menghilangkan kunci benang yang sangat mahal. Satu-satunya alasan untuk digunakan atomicadalah jika properti Anda mungkin disetel dari beberapa utas (dalam hal ini menghilangkannya dapat menyebabkan pelepasan berlebih atau kebocoran).
Adam Kaplan
295

Sebelum Anda tahu tentang atribut @ properti, Anda harus tahu apa gunanya @ properti.

  • @ properti menawarkan cara untuk mendefinisikan informasi bahwa kelas dimaksudkan untuk merangkum. Jika Anda mendeklarasikan objek / variabel menggunakan @property , maka objek / variabel itu akan dapat diakses oleh kelas lain yang mengimpor kelasnya.

  • Jika Anda mendeklarasikan objek menggunakan @property di file header, maka Anda harus mensintesisnya menggunakan @synthesize dalam file implementasi. Ini membuat objek KVC sesuai . Secara default, kompiler akan mensintesis metode accessor untuk objek ini.

  • metode accessor adalah: setter dan pengambil.

Contoh: .h

@interface XYZClass : NSObject
@property (nonatomic, retain) NSString *name;
@end

.m

@implementation XYZClass
@synthesize name;
@end

Sekarang kompiler akan mensintesis metode aksesor untuk nama .

XYZClass *obj=[[XYZClass alloc]init];
NSString *name1=[obj name]; // get 'name'
[obj setName:@"liza"]; // first letter of 'name' becomes capital in setter method
  • Daftar atribut @property

    atomik, nonatomik, simpan, salin, baca saja, baca-tulis, tetapkan, kuat, pengambil = metode, setter = metode, tidak aman_tidakdikirim

  • atom adalah perilaku default. Jika suatu objek dinyatakan sebagai atom maka itu menjadi thread-safe. Thread-safe berarti, pada suatu waktu hanya satu thread dari instance tertentu dari kelas yang dapat memiliki kontrol atas objek itu.

Jika utas melakukan metode pengambil maka utas lainnya tidak dapat melakukan metode setter pada objek itu. Itu lambat.

@property NSString *name; //by default atomic`
@property (atomic)NSString *name; // explicitly declared atomic`
  • nonatomik tidak aman untuk benang. Anda dapat menggunakan atribut properti nonatomik untuk menentukan bahwa pengakses yang disintesis cukup menetapkan atau mengembalikan nilai secara langsung, tanpa jaminan tentang apa yang terjadi jika nilai yang sama diakses secara bersamaan dari utas yang berbeda.

Karena alasan ini, lebih cepat mengakses properti nonatomik daripada properti atomik.

@property (nonatomic)NSString *name;   
  • retain diperlukan saat atribut adalah penunjuk ke objek.

Metode setter akan meningkatkan jumlah retensi objek, sehingga akan menempati memori dalam kumpulan autorelease.

@property (retain)NSString *name;
  • copy Jika Anda menggunakan copy, Anda tidak bisa menggunakan retain. Menggunakan copy instance dari kelas akan berisi salinannya sendiri.

Bahkan jika string yang dapat diubah diatur dan kemudian diubah, instance menangkap nilai apa pun yang dimilikinya pada saat itu ditetapkan. Tidak ada metode setter dan pengambil yang akan disintesis.

@property (copy) NSString *name;

sekarang,

NSMutableString *nameString = [NSMutableString stringWithString:@"Liza"];    
xyzObj.name = nameString;    
[nameString appendString:@"Pizza"]; 

nama akan tetap tidak terpengaruh.

  • readonly Jika Anda tidak ingin mengizinkan properti diubah melalui metode setter, Anda dapat mendeklarasikan properti readonly.

Compiler akan menghasilkan pengambil, tetapi bukan penyetel.

@property (readonly) NSString *name;
  • readwrite adalah perilaku default. Anda tidak perlu menentukan atribut readwrite secara eksplisit.

Ini kebalikan dari readonly.

@property (readwrite) NSString *name;
  • assign akan menghasilkan setter yang memberikan nilai ke variabel instan secara langsung, daripada menyalin atau mempertahankannya. Ini terbaik untuk tipe primitif seperti NSInteger dan CGFloat, atau objek yang tidak Anda miliki secara langsung, seperti delegasi.

Ingatlah, simpan dan tetapkan pada dasarnya bisa dipertukarkan saat pengumpulan sampah diaktifkan.

@property (assign) NSInteger year;
  • kuat adalah pengganti untuk mempertahankan.

Muncul dengan ARC.

@property (nonatomic, strong) AVPlayer *player; 
  • pengambil = metode Jika Anda ingin menggunakan nama yang berbeda untuk metode pengambil, Anda dapat menentukan nama khusus dengan menambahkan atribut ke properti.

Dalam kasus properti Boolean (properti yang memiliki nilai YA atau TIDAK), biasanya metode pengambil dimulai dengan kata "is"

@property (getter=isFinished) BOOL finished;
  • setter = method Jika Anda ingin menggunakan nama yang berbeda untuk metode setter, Anda dapat menentukan nama khusus dengan menambahkan atribut ke properti.

Metode ini harus diakhiri dengan tanda titik dua.

@property(setter = boolBool:) BOOL finished;
  • unsafe_unretained Ada beberapa kelas di Cocoa dan Cocoa Touch yang belum mendukung referensi yang lemah, yang berarti Anda tidak dapat mendeklarasikan properti yang lemah atau variabel lokal yang lemah untuk melacaknya. Kelas-kelas ini termasuk NSTextView, NSFont dan NSColorSpace, dll. Jika Anda perlu menggunakan referensi yang lemah ke salah satu kelas ini, Anda harus menggunakan referensi yang tidak aman.

Referensi yang tidak aman mirip dengan referensi yang lemah karena tidak menjaga objek terkait tetap hidup, tetapi tidak akan disetel ke nol jika objek tujuan dideallocated.

@property (unsafe_unretained) NSObject *unsafeProperty;

Jika Anda perlu menentukan beberapa atribut, cukup sertakan sebagai daftar yang dipisahkan koma, seperti ini:

@property (readonly, getter=isFinished) BOOL finished;
liza
sumber
Selain itu, lemah berarti bahwa tidak ada jumlah referensi ke referensi ke objek, tetapi referensi sama sekali, atau tidak direferensikan sama sekali. Agak seperti "ya, sesuatu merujuk saya" vs. "9 referensi kepada saya ada" (yang seperti apa kuatnya)
Alex Zavatone
6
Abaikan baris dalam jawaban mengenai pengumpulan sampah, karena pengumpulan sampah sudah tidak digunakan lagi di Mac OS X dan tidak ada di iOS per dokumentasi Apple .
Basil Bourque
4
"Catatan: Atomicity properti tidak identik dengan keamanan utas objek." - dari developer.apple.com/library/mac/documentation/Cocoa/Conceptual/…
jk7
1
"Jika Anda mendeklarasikan objek menggunakan @propertydalam file header, maka Anda harus mensintesisnya menggunakan @synthesizedalam file implementasi." Tidak selalu. Misalnya, "Secara default, readwriteproperti akan didukung oleh variabel instan, yang akan disintesis lagi secara otomatis oleh kompiler." Dari dok .
Franklin Yu
4
@ Liza Ini adalah jawaban yang bagus. Mengapa ini bukan jawaban yang diterima. Ini menyampaikan penjelasan yang jauh lebih luas daripada jawaban yang saat ini diterima. Saya terkadang tidak mengerti StackOverflow?
Charles Robertson
149

Setelah membaca banyak artikel, saya memutuskan untuk menggabungkan semua informasi atribut:

  1. atom // default
  2. nonatomik
  3. strong = retain // default
  4. lemah = tidak aman_kurang
  5. menahan
  6. tetapkan // default
  7. tidak aman_tidak dijaga
  8. menyalin
  9. dibaca saja
  10. readwrite // default

Di bawah ini adalah tautan ke artikel terperinci di mana Anda dapat menemukan atribut-atribut ini.

Terima kasih banyak kepada semua orang yang memberikan jawaban terbaik di sini !!

Atribut properti variabel atau Pengubah di iOS

Berikut ini Contoh Deskripsi dari Artikel

  1. atomic -Atomic berarti hanya satu utas mengakses variabel (tipe statis). -Atomik adalah thread yang aman. -tapi itu lambat dalam kinerja -atomik adalah perilaku default -Atom pengarah di lingkungan non sampah yang dikumpulkan (yaitu ketika menggunakan retain / release / autorelease) akan menggunakan kunci untuk memastikan bahwa utas lain tidak mengganggu pengaturan / pengambilan yang benar dari nilai. -itu sebenarnya bukan kata kunci.

Contoh:

@property (retain) NSString *name;

@synthesize name;
  1. nonatomic -Nonatomic berarti multiple thread mengakses variabel (tipe dinamis). -Nonatomic adalah utas yang tidak aman. -tapi itu cepat dalam kinerja -Natomik BUKAN perilaku default, kita perlu menambahkan kata kunci nonatomik dalam atribut properti. -itu dapat mengakibatkan perilaku tak terduga, ketika dua proses (utas) yang berbeda mengakses variabel yang sama pada saat yang sama.

Contoh:

@property (nonatomic, retain) NSString *name;

@synthesize name;

Menjelaskan:

Misalkan ada properti string atom yang disebut "name", dan jika Anda memanggil [self setName: @ "A"] dari thread A, panggil [self setName: @ "B"] dari thread B, dan panggil [self name] dari utas C, maka semua operasi pada utas berbeda akan dilakukan secara seri yang artinya jika satu utas mengeksekusi setter atau pengambil, maka utas lainnya akan menunggu. Ini membuat properti "nama" aman untuk baca / tulis tetapi jika utas lain memanggil [nama rilis] secara bersamaan maka operasi ini dapat menghasilkan crash karena tidak ada panggilan setter / pengambil yang terlibat di sini. Yang berarti suatu objek membaca / menulis aman (ATOMIC) tetapi tidak aman sebagai utas lain dapat secara bersamaan mengirim semua jenis pesan ke objek. Pengembang harus memastikan keamanan utas untuk objek tersebut.

Jika properti "nama" adalah nonatomik, maka semua utas dalam contoh di atas - A, B, C dan D akan dieksekusi secara bersamaan menghasilkan hasil yang tidak terduga. Dalam hal atom, salah satu dari A, B atau C akan dieksekusi terlebih dahulu tetapi D masih dapat dieksekusi secara paralel.

  1. kuat (iOS4 = retain) -itu mengatakan "simpan ini di tumpukan sampai saya tidak menunjuk lagi" -dengan kata lain "Saya pemiliknya, Anda tidak dapat membatalkan ini sebelum bertujuan baik-baik saja dengan yang sama seperti mempertahankan" - Anda menggunakan kuat hanya jika Anda perlu mempertahankan objek. -Dengan default semua variabel instan dan variabel lokal adalah pointer kuat. -Kami umumnya menggunakan kuat untuk UIViewControllers (orang tua item UI) -strong digunakan dengan ARC dan pada dasarnya membantu Anda, dengan tidak perlu khawatir tentang mempertahankan jumlah benda. ARC secara otomatis melepaskannya untuk Anda ketika Anda selesai dengan itu. Menggunakan kata kunci yang kuat berarti Anda memiliki objek.

Contoh:

@property (strong, nonatomic) ViewController *viewController;

@synthesize viewController;
  1. lemah (iOS4 = unsafe_unretained) -itu mengatakan "simpan ini selama orang lain menunjukkannya dengan kuat" - hal yang sama seperti menetapkan, tidak ada penahan atau pelepasan - Referensi "lemah" adalah referensi yang tidak Anda pertahankan. -Kami umumnya menggunakan lemah untuk IBOutlets (UIViewController's Childs). Ini berfungsi karena objek anak hanya perlu ada selama objek induknya. -sebuah referensi lemah adalah referensi yang tidak melindungi objek yang dirujuk dari pengumpulan oleh pengumpul sampah. -Weak pada dasarnya menetapkan, properti yang tidak ditangguhkan. Kecuali ketika objek dideallocated, pointer lemah secara otomatis diatur ke nol

Contoh:

@property (weak, nonatomic) IBOutlet UIButton *myButton;

@synthesize myButton;

Penjelasan Kuat & Lemah, Terima Kasih kepada BJ Homer :

Bayangkan objek kita adalah seekor anjing, dan anjing itu ingin melarikan diri (dideallocated). Pointer yang kuat seperti tali pada anjing. Selama Anda memiliki tali pengikat pada anjing, anjing itu tidak akan lari. Jika lima orang mengikatkan tali penuntun mereka pada satu anjing, (lima penunjuk kuat pada satu benda), maka anjing itu tidak akan melarikan diri sampai kelima tali penuntun terlepas. Pointer yang lemah, di sisi lain, seperti anak-anak kecil yang menunjuk ke anjing dan berkata, "Lihat! Seekor anjing!" Selama anjing itu masih terikat, anak-anak kecil masih bisa melihat anjing itu, dan mereka masih akan menunjuk ke sana. Namun, segera setelah semua tali terlepas, anjing itu melarikan diri tidak peduli berapa banyak anak kecil yang menunjuk padanya. Segera setelah penunjuk kuat terakhir (tali penuntun) tidak lagi menunjuk ke suatu objek, objek tersebut akan dibatalkan alokasinya, dan semua penunjuk lemah akan dihilangkan. Kapan kita menggunakan yang lemah? Satu-satunya waktu Anda ingin menggunakan lemah, adalah jika Anda ingin menghindari siklus mempertahankan (misalnya orang tua mempertahankan anak dan anak mempertahankan orang tua sehingga tidak pernah dilepaskan).

  1. retain = strong -it dipertahankan, nilai lama dilepaskan dan ditugaskan-retain menentukan nilai baru harus dikirim -tahan pada tugas dan nilai lama dikirim -release-retain sama dengan kuat. -apple mengatakan jika Anda tetap mempertahankannya akan otomatis dikonversi / berfungsi seperti kuat saja. -metoda seperti "alokasi" termasuk "mempertahankan" implisit

Contoh:

@property (nonatomic, retain) NSString *name;

@synthesize name;
  1. assign -assign adalah default dan hanya melakukan penugasan variabel -assign adalah atribut properti yang memberitahu kompiler bagaimana mensintesis implementasi setter properti -Saya akan menggunakan assign untuk properti primitif C dan lemah untuk referensi lemah ke objek Objective-C.

Contoh:

@property (nonatomic, assign) NSString *address;

@synthesize address;
  1. tidak aman_tidak dijaga

    -unsafe_unretained adalah kualifikasi kepemilikan yang memberi tahu ARC cara memasukkan panggilan retain / release -unsafe_unretained adalah versi penetapan versi ARC.

Contoh:

@property (nonatomic, unsafe_unretained) NSString *nickName;

@synthesize nickName;
  1. copy-copy diperlukan ketika objek bisa berubah. -kopi menentukan nilai baru harus dikirim -kopi pada tugas dan nilai lama dikirim -rilis. -copy seperti mempertahankan mengembalikan objek yang harus Anda lepaskan secara eksplisit (misalnya, dalam dealloc) di lingkungan yang dikumpulkan tanpa sampah. -Jika Anda menggunakan salinan maka Anda masih perlu melepaskan itu di dealloc. -Gunakan ini jika Anda membutuhkan nilai objek seperti saat ini, dan Anda tidak ingin nilai itu mencerminkan perubahan yang dibuat oleh pemilik objek lain. Anda harus melepaskan objek setelah selesai karena Anda menyimpan salinannya.

Contoh:

@property (nonatomic, copy) NSArray *myArray;

@synthesize myArray;
swiftBoy
sumber
2
Saya pikir setelah arc, retain tidak digunakan lagi.
mert
1
daftar lengkap melewatkan 2 item opsi: setter dan pengambil, yang juga merupakan satu-satunya opsi yang membutuhkan argumen.
Scott Chu
strong atau retain adalah default untuk tipe objek saja. Itu tidak bisa digunakan untuk tipe primitif.
Saleh Enam Shohag
9

Properti atom dapat diakses hanya dengan satu utas pada satu waktu. Ini aman dari utas . Default adalah atom. Harap dicatat bahwa tidak ada atom kata kunci

Nonatomik berarti beberapa utas dapat mengakses item. Ini utas yang tidak aman

Jadi seseorang harus sangat berhati-hati saat menggunakan atom. Karena itu mempengaruhi kinerja kode Anda

Kannan Prasad
sumber
3
"Catatan: Atomicity properti tidak identik dengan keamanan utas objek." dari developer.apple.com/library/mac/documentation/Cocoa/Conceptual/…
jk7