Apakah properti yang dideklarasikan memerlukan variabel instance yang sesuai?

101

Apakah properti di Objective-C 2.0 memerlukan variabel instan terkait untuk dideklarasikan? Misalnya, saya terbiasa melakukan sesuatu seperti ini:

MyObject.h

@interface MyObject : NSObject {
NSString *name;
}
@property (nonatomic, retain) NSString *name;
@end

MyObject.m

@implementation
@synthesize name;
@end

Namun, bagaimana jika saya melakukan ini sebagai gantinya:

MyObject.h

@interface MyObject : NSObject {
}
@property (nonatomic, retain) NSString *name;
@end

Apakah ini masih berlaku? Dan apakah ini berbeda dengan contoh saya sebelumnya?

indragie.dll
sumber
Mengapa 'MyObject.h' kedua yang dicetak tebal bukan 'MyObject.m'?
Ríomhaire

Jawaban:

93

Jika Anda menggunakan Modern Objective-C Runtime (iOS 3.x atau yang lebih baru, atau Snow Leopard 64-bit atau yang lebih baru), Anda tidak perlu menentukan ivars untuk properti Anda dalam kasus seperti ini.

Ketika Anda @synthesizememiliki properti, ivar akan disintesis juga untuk Anda. Ini menyiasati skenario "fragile-ivar". Anda dapat membaca lebih lanjut tentang itu di Cocoa with Love

jbrennan.dll
sumber
71

Di antarmuka Anda, Anda dapat secara resmi mendeklarasikan variabel instance di antara tanda kurung kurawal, atau melalui @propertykurung kurawal, atau keduanya. Bagaimanapun, mereka menjadi atribut kelas. Perbedaannya adalah jika Anda mendeklarasikan @property, maka Anda dapat mengimplementasikan menggunakan @synthesize, yang otomatis mengkodekan pengambil / penyetel untuk Anda. Penyetel pengkode otomatis menginisialisasi bilangan bulat dan mengapung ke nol, misalnya. JIKA Anda mendeklarasikan variabel instance, dan JANGAN menentukan variabel terkait @property, Anda tidak dapat menggunakan @synthesizedan harus menulis getter / setter Anda sendiri.

Anda selalu dapat menimpa pengambil / penyetel kode otomatis dengan menentukan milik Anda sendiri. Ini biasanya dilakukan dengan managedObjectContextproperti yang dimuat secara lambat. Jadi, Anda mendeklarasikan milik Anda managedObjectContextsebagai properti, tetapi juga menulis -(NSManagedObjectContext *)managedObjectContextmetode. Ingatlah bahwa metode, yang memiliki nama yang sama dengan variabel / properti instance adalah metode "pengambil".

The @propertyMetode deklarasi juga memungkinkan Anda pilihan lain, seperti retaindan readonly, yang metode deklarasi variabel contoh tidak. Pada dasarnya, ivaradalah cara lama, dan @propertymemperluasnya serta membuatnya lebih menarik / lebih mudah. Anda bisa merujuk ke salah satunya dengan menggunakan diri. awalan, atau tidak, tidak masalah selama namanya unik untuk kelas itu. Jika tidak, jika superclass Anda memiliki nama properti yang sama dengan Anda, maka Anda harus mengatakan like self.name atau super.name untuk menentukan nama yang Anda bicarakan.

Dengan demikian, Anda akan melihat semakin sedikit orang yang mendeklarasikan ivars di antara kurung kurawal, dan sebaliknya beralih ke hanya menentukan @property, lalu melakukan @synthesize. Anda tidak dapat melakukannya @synthesizedalam implementasi Anda tanpa yang sesuai @property. Synthesizer hanya mengetahui jenis atributnya dari @propertyspesifikasi. Pernyataan sintesis juga memungkinkan Anda untuk mengganti nama properti, sehingga Anda dapat merujuk ke properti dengan satu nama (singkatan) di dalam kode Anda, tetapi di luar di file .h gunakan nama lengkap. Namun, dengan pelengkapan otomatis yang sangat keren yang dimiliki Xcode sekarang, ini kurang menguntungkan, tetapi masih ada.

Semoga ini bisa membantu menjernihkan semua kebingungan dan misinformasi yang beredar di luar sana.

PapaSmurf
sumber
Sekarang hari tidak wajib untuk menulis @synthesize. Jadi bagaimana jawaban ini valid dalam kasus itu!
raaz
Anda tidak HARUS mendeklarasikan <code> @property ... @ synthesize </code>. Menggunakan sintesis membebaskan Anda dari keharusan menulis pengambil / penyetel dalam implementasi Anda. Jika Anda tidak mensintesis, maka Anda harus menggulung pengambil / penyetel Anda sendiri
PapaSmurf
2
@PapaSmur Itu salah. Anda dapat menggunakan @property, dan tidak menggunakan @synthesizedan tidak menerapkannya sendiri. Kompiler akan otomatis synthesizeuntuk Anda, tanpa harus menuliskannya lagi.
jbrennan
8

ini bekerja dua arah tetapi jika Anda tidak mendeklarasikannya dalam kurung kurawal, Anda tidak akan melihat nilainya di debugger di xcode.

rickm
sumber
3

Dari dokumentasi:

Secara umum, perilaku properti identik pada runtime modern dan lawas (lihat "Versi dan Platform Waktu Proses" di Panduan Pemrograman Waktu Proses Objective-C). Ada satu perbedaan utama: runtime modern mendukung sintesis variabel instance sedangkan runtime lama tidak.

Agar @synthesize berfungsi pada runtime lama, Anda harus memberikan variabel instance dengan nama yang sama dan jenis properti yang kompatibel atau menentukan variabel instance lain yang ada di pernyataan @synthesize. Dengan runtime modern, jika Anda tidak menyediakan variabel instance, compiler akan menambahkannya untuk Anda.

Charlie Elliott
sumber
3

Jika Anda menggunakan XCode 4.4 atau yang lebih baru, ini akan menghasilkan kode sintesis variabel instance untuk Anda.

Anda hanya perlu mendeklarasikan properti seperti di bawah ini; itu akan menghasilkan kode sintesis dan variabel contoh yang mendeklarasikan kode untuk Anda.

@property (nonatomic, strong) NSString *name;

itu akan menghasilkan kode sintesis sebagai

@synthesize name = _name;

dan Anda dapat mengakses variabel instance menggunakan _name yang mirip dengan yang dideklarasikan

NSString* _name

tetapi jika Anda mendeklarasikan properti read-only itu seperti

@property (nonatomic, strong, readonly) NSString *name;

itu akan menghasilkan kode

@synthesize name;

atau

@synthesize name = name; 

Jadi, Anda harus mengakses nama variabel instan tanpa awalan "_" dengan cara apa pun Anda dapat menulis kode sintesis Anda sendiri, maka kompiler akan menghasilkan kode untuk Anda. kamu bisa menulis

@synthesize name = _name;
Shafraz Buhary
sumber
1

Bahasa Pemrograman Objective-C: Petunjuk Implementasi Properti

Ada perbedaan dalam perilaku sintesis pengakses yang bergantung pada waktu proses (lihat juga "Perbedaan Waktu Proses"):

  • Untuk runtime lama, variabel instance harus sudah dideklarasikan di blok @interface kelas saat ini. Jika variabel instance dengan nama yang sama dengan properti ada, dan jika tipenya kompatibel dengan tipe properti, itu akan digunakan — jika tidak, Anda akan mendapatkan kesalahan compiler.

  • Untuk runtime modern (lihat "Versi dan Platform Waktu Proses" di Panduan Pemrograman Waktu Proses Objective-C), variabel instance disintesis sesuai kebutuhan. Jika variabel contoh dengan nama yang sama sudah ada, itu digunakan.

Nate
sumber