error: properti atom yang dapat ditulis tidak dapat memasangkan setter / pengambil yang disintesis dengan setter / pengambil yang ditentukan pengguna

128

Saya baru-baru ini mencoba untuk mengkompilasi proyek Xcode yang lebih lama (yang digunakan untuk mengkompilasi dengan baik), dan sekarang saya melihat banyak kesalahan dari formulir ini:

error: writable atomic property 'someProperty' cannot pair a synthesized setter/getter with a user defined setter/getter

Pola kode yang menyebabkan kesalahan ini selalu terlihat seperti ini:

// Interface:

@property (retain) NSObject * someProperty;

// Implementation:

@synthesize someProperty; // to provide the getter
- (void)setSomeProperty:(NSObject *)newValue
{
    //..
}

Saya bisa melihat mengapa kesalahan ini terjadi. Saya memberitahu kompiler untuk mensintesis aksesor properti saya (baik pengambil dan penyetel), dan kemudian segera saya menimpa penyetel secara manual. Kode itu selalu berbau sedikit.

Jadi, apa cara yang tepat untuk melakukan ini? Jika saya menggunakan @dynamicalih-alih @synthesize, saya harus menulis getter juga. Apakah itu satu-satunya jalan?

e.James
sumber
Apakah ini hanya terjadi pada atomicproperti? Dalam hal sifat atom, mungkin merupakan ide yang baik untuk menjaga pasangan pengambil / penyetel sinkron sehubungan dengan strategi penguncian. Ini sulit jika satu bagian disintesis sementara yang lain adalah kode kustom.
Nikolai Ruhe
Itu pasti hilang jika saya membuat properti menjadi nonatomik. Menarik. Saya bahkan belum memikirkan masalah sinkronisasi.
e.James
Saya mengunjungi topik ini untuk menemukan solusi untuk masalah yang sebenarnya. Saya tidak benar-benar ingin menulis rajin dan rajin. Oh well ...
Constantino Tsarouhas
Secara default setiap properti adalah atom dan kita perlu membuatnya nonatomik secara eksplisit. Properti atom adalah thread yang aman, jadi kami tidak dapat mengimplementasikan setter dan pengambil untuk mereka karena itu akan mengubah fungsionalitasnya yang aman. Saya harap Anda mendapatkan alasan mengapa Anda mendapatkan kesalahan ini.
Mohd Haider

Jawaban:

218

Saya memiliki masalah yang sama dan setelah melakukan sedikit riset, inilah kesimpulan saya tentang masalah ini:

Kompiler memperingatkan Anda tentang @propertyyang Anda nyatakan sebagai atom (yaitu dengan menghilangkan nonatomickata kunci), namun Anda memberikan implementasi yang tidak lengkap tentang bagaimana menyinkronkan akses ke properti itu.

Untuk menghilangkan peringatan itu:

Jika Anda mendeklarasikan @propertysebagai atom maka lakukan salah satu dari yang berikut:

  • gunakan @dynamicatau;
  • menggunakan @synthesize dan simpan setter dan pengambil yang disintesis atau;
  • memberikan implementasi manual keduanya setter dan getter (tanpa menggunakan salah satu arahan atas).

Jika Anda mendeklarasikan @property dengan (nonatomic)maka Anda dapat mencampur implementasi getter dan setter manual dan disintesis.

Pembaruan: Catatan tentang Sintesis Otomatis Properti

Pada LLVM 4.0, CLang menyediakan sintesis otomatis untuk properti yang dinyatakan tidak @dynamic. Secara default, bahkan jika Anda mengabaikannya @synthesize, kompiler akan menyediakan metode pengambil dan penyetel untuk Anda. Namun, aturan untuk sifat atom masih sama: Entah membiarkan compiler memberikan baik pengambil dan setter, OR menerapkannya baik sendiri!

ok
sumber
Terima kasih! "nyatakan properti dengan (nonatomik)"
Nianliang
14

Anda perlu menerapkan rajin dan giat. Contoh:

// Interface:

@property (retain) NSObject * someProperty;

// Implementation:

- (void)setSomeProperty:(NSObject *)newValue
{
    @synchronized (self)
    {
        // ...
    }
}

- (NSObject *)someProperty
{
    NSObject *ret = nil;

    @synchronized (self)
    {
        ret = [[someProperty retain] autorelease];
    }

    return ret;
}
arturgrigor
sumber
12

Pertanyaan ini, di antara hit top lain yang Anda dapatkan dari mencari "properti kustom objektif C", tidak diperbarui dengan informasi tentang "setter =" atau "getter =".

Jadi, untuk memberikan informasi lebih lanjut tentang pertanyaan ini:

Anda dapat menyediakan panggilan properti dengan metode Anda sendiri dengan menulis

    @property(setter = MySetterMethod:, getter = MyGetterMethod)

Perhatikan titik dua untuk metode penyetel yang disediakan.

Referensi dokumentasi Apple

EDIT: Saya tidak yakin bagaimana perubahan baru pada properti Objective-C (mereka jauh lebih cerdas sekarang) mengubah jawaban untuk pertanyaan ini. Mungkin itu semua harus ditandai sebagai ketinggalan zaman.

Matias Forbord
sumber
Saya menemukan bahwa pengaturan metode penyetel tidak benar-benar menghapus peringatan. mis -> "@property (assign, setter = setDelegate :) id delegate;" Dalam hal ini yang bisa saya lakukan adalah menambahkan getter saya sendiri atau menambahkan properti nonatomik, yang saya tidak yakin jika saya harus, mengingat bahwa saya menetapkan delegasi sendiri 'secara atomis', tidak masalah memiliki properti nonatomik , atau jadi saya mengerti.
David van Dugteren
Menarik, David. Apa "versi" dari Objective-C ini dalam (saya kira mengatakan versi-XCode akan lebih membantu)? Saya tidak yakin apa perubahan terbaru ke Objective-C, khususnya dengan iOS 6 mempengaruhi ini.
Matias Forbord
0

Bagi orang lain yang mendapatkan kesalahan ini bukan karena alasan OP dijelaskan, Anda mungkin memiliki masalah yang sama dengan saya:

Anda memiliki @ properti dengan nama yang sama dengan metode - ().

Sesuatu seperti ini:

@property UIView *mainView;

-(UIView *)mainView;
Albert Renshaw
sumber