Apa sebenarnya yang dilakukan @synthesize?


148

Saya telah melihat potongan kode berikut:

//example.h
MKMapView * mapView1;
@property (nonatomic, retain) MKMapView * mapView;

//example.m
@synthesize mapView = mapView1

Apa hubungan antara mapViewdan mapView1? Apakah itu membuat setdan getmetode untuk mapView1?


1
Pembaruan: tetapi dengan set alat terbaru @synthesize sekarang (hampir) tidak pernah diperlukan. Lihat jawaban untuk Pertanyaan Stack Overflow Lainnya .
Ali Beadle

Jawaban:


228

Dalam contoh Anda, mapView1adalah variabel instan (ivar), sepotong penyimpanan memori yang dimiliki oleh instance kelas yang didefinisikan dalam example.hdan example.m. mapViewadalah nama sebuah properti . Properti adalah atribut dari sebuah objek yang dapat membaca atau diatur dengan menggunakan notasi dot: myObject.mapView. Sebuah properti tidak memiliki harus didasarkan pada sebuah Ivar, tapi kebanyakan properti yang. The @propertydeklarasi hanya memberitahu dunia bahwa ada sifat yang disebut mapView.

@synthesize mapView = mapView1;

Baris ini memberi tahu kompiler untuk membuat setter dan pengambil mapView, dan mereka harus menggunakan ivar yang disebut mapView1. Tanpa = mapView1bagian itu, kompiler akan menganggap bahwa properti dan ivar memiliki nama yang sama. (Dalam hal ini, itu akan menghasilkan kesalahan kompiler, karena tidak ada ivar yang dipanggil mapView.)

Hasil @synthesizepernyataan ini mirip dengan jika Anda telah menambahkan kode ini sendiri:

-(MKMapView *)mapView
{
   return mapView1;
}

-(void)setMapView:(MKMapView *)newMapView
{
  if (newMapView != mapView1)
  {
    [mapView1 release];
    mapView1 = [newMapView retain];
  }
}

Jika Anda menambahkan kode itu sendiri ke kelas, Anda dapat mengganti @synthesizepernyataan itu dengan

@dynamic mapView;

Hal utama adalah memiliki perbedaan konseptual yang sangat jelas antara ivar dan properti. Mereka benar-benar dua konsep yang sangat berbeda.


31

@synthesize menciptakan pengambil dan penyetel untuk variabel.

Ini memungkinkan Anda menentukan beberapa atribut untuk variabel Anda dan ketika Anda @synthesizeproperti itu ke variabel Anda menghasilkan pengambil dan penyetel untuk variabel.

Nama properti bisa sama dengan nama variabel. Kadang-kadang orang ingin itu berbeda sehingga menggunakannya di initatau deallocatau ketika parameter dilewatkan dengan nama variabel yang sama.


16

Dari dokumentasi :

Anda menggunakan kata kunci @synthesize untuk memberi tahu kompiler bahwa itu harus mensintesis setter dan / atau metode pengambil untuk properti jika Anda tidak menyediakannya dalam blok @implementation.


8

Karena saya baru saja mengalami masalah ini ketika mengedit kode lama saya ingin membuat catatan tambahan untuk jawaban yang ada yang perlu diperhatikan.

Bahkan dengan versi kompiler yang lebih baru terkadang membuat perbedaan jika Anda menghilangkan @synthesize propertyNameatau tidak .

Jika Anda mendeklarasikan variabel instan tanpa garis bawah saat masih mensintesisnya, seperti:

Tajuk:

@interface SomeClass : NSObject {
   int someInt;
}
@property int someInt;
@end

Penerapan:

@implementation SomeClass
@synthesize someInt;
@end

self.someInt akan mengakses variabel yang sama dengan someInt . Tidak menggunakan garis bawah terkemuka untuk ivars tidak mengikuti konvensi penamaan tetapi saya hanya datang ke situasi di mana saya harus membaca dan memodifikasi kode tersebut.

Tetapi jika Anda sekarang berpikir "Hei, @synthesize tidak penting lagi karena kami menggunakan kompiler yang lebih baru" Anda salah! Kelas Anda kemudian akan menghasilkan memiliki dua ivar , yaitu someIntditambah _someIntvariabel autogenerated . Dengan demikian self.someIntdan someInttidak akan membahas variabel yang sama lagi. Jika Anda tidak mengharapkan perilaku seperti yang saya lakukan ini mungkin membuat Anda sakit kepala untuk mengetahuinya.


"sinkronisasi"! = "disintesis"?
jameshfisher

Ya, ini adalah 2 konsep yang berbeda. @synchronizeadalah arahan untuk bagaimana menyinkronkan utas saat mengakses properti dan @synthesizeuntuk mengikat properti ke variabel instan melalui getter dan setter.
Lars Blumberg

1
Komentar jameshfisher dimaksudkan untuk mengingatkan Anda bahwa Anda bingung menyinkronkan dan mensintesis jawaban Anda. Anda menggunakan keduanya secara bergantian.
Maple

1
Terima kasih telah membuat saya sadar akan hal itu! Saya benar-benar mengawasi itu, saya telah memperbarui jawaban untuk tidak menggunakan kata kunci @sinkronisasi yang tidak ada.
Lars Blumberg

Dalam hal ini, Xcode 10 akan memperingatkan tentang masalah ini: Autosynthesized property 'someInt' will use synthesized instance variable '_someInt', not existing instance variable 'someInt'. (Saya tidak tahu di versi xcode mana peringatan ini ditambahkan.)
zwcloud

7

Per dokumentasi Apple @Synthesize hanya digunakan untuk mengubah nama variabel instan. Sebagai contoh

@property NSString *str;

@synthesize str = str2; 

Sekarang di kelas Anda tidak dapat menggunakan _strkarena baris di atas telah mengubah nama variabel instance menjadistr2

@property memungkinkan objek untuk digunakan oleh objek di kelas lain, atau dengan kata lain membuat objek publik.


3
Rupanya, dimulai dengan Xcode 4.4, Clang memberikan dukungan untuk autosintesis properti yang dideklarasikan. Jadi @sintesis tidak lagi diperlukan untuk sebagian besar kasus. Lihat useyourloaf.com/blog/2012/08/01/…
huyz

5

Saat Anda membuat properti di @interface, properti itu akan secara otomatis kembali oleh variabel instan bernama _propertyName. Jadi ketika Anda membuat properti bernama firstName, kompiler di belakang layar akan membuat variabel instan bernama _firstName secara default. Compiler juga akan membuat metode pengambil dan penyetel untuk Anda (mis. FirstName, setFirstName).

Sekarang ketika Anda mensintesis properti dengan @sintesize firstName, Anda cukup memberi tahu kompilator ganti nama variabel instan saya (_firstName) dengan firstName. Jika Anda ingin mengganti nama variabel instance yang dicadangkan Anda dengan nama yang berbeda, Anda dapat menetapkan nama yang berbeda saat mensintesiskan nama properti (yaitu @sintesize firstName = myFirstName), dengan melakukan ini properti Anda didukung oleh variabel instance bernama myFirstname.

Jadi, singkatnya, sebagian besar waktu @synthesize digunakan untuk mengubah nama variabel instan Anda didukung oleh properti Anda.


2

Lihat dokumen apel

Pada dasarnya synthesize menciptakan metode setMapView dan mapView yang mengatur dan mendapatkan mapView1


2

Ini menciptakan pengambil dan penyetel untuk objek Anda. Anda dapat mengakses dengan sesuatu seperti ini:

MKMapView* m = object.mapView;

atau

object.mapView = someMapViewObject

mapView1 adalah nama dari ivar di kelas, mapView adalah nama untuk metode pengambil / penyetel.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.