Saya telah mendeklarasikan properti hanya-baca di antarmuka saya seperti ini:
@property (readonly, nonatomic, copy) NSString* eventDomain;
Mungkin saya salah paham tentang properti, tetapi saya pikir ketika Anda mendeklarasikannya sebagai readonly
, Anda dapat menggunakan penyetel yang dihasilkan di dalam file implementasi ( .m
), tetapi entitas eksternal tidak dapat mengubah nilainya. Pertanyaan SO ini mengatakan bahwa itulah yang seharusnya terjadi. Itulah perilaku yang saya kejar. Namun, ketika mencoba menggunakan penyetel standar atau sintaks titik untuk menyetel eventDomain
di dalam metode init saya, ini memberi saya unrecognized selector sent to instance.
kesalahan. Tentu saja aku akan @synthesize
mendapatkan propertinya. Mencoba menggunakannya seperti ini:
// inside one of my init methods
[self setEventDomain:@"someString"]; // unrecognized selector sent to instance error
Jadi, apakah saya salah memahami readonly
pernyataan tentang properti? Atau ada hal lain yang sedang terjadi?
.h
? Kalau tidak, saya tidak melihat bagaimana ini akan mengekspos setter publik. Terima kasihEiko dan yang lainnya memberikan jawaban yang benar.
Berikut cara yang lebih sederhana: Akses langsung variabel anggota pribadi.
Contoh
Di file header .h:
@property (strong, nonatomic, readonly) NSString* foo;
Dalam implementasi file .m:
Itu saja, itu saja yang Anda butuhkan. Tidak repot, tidak repot.
Detail
Mulai Xcode 4.4 dan LLVM Compiler 4.0 ( Fitur Baru di Xcode 4.4 ), Anda tidak perlu mengacaukan tugas-tugas yang dibahas dalam jawaban lain:
synthesize
kunciSetelah mendeklarasikan properti
foo
, Anda dapat mengasumsikan Xcode telah menambahkan variabel anggota pribadi bernama dengan awalan garis bawah:_foo
.Jika properti dideklarasikan
readwrite
, Xcode menghasilkan metode pengambil bernamafoo
dan penyetel bernamasetFoo
. Metode ini secara implisit dipanggil ketika Anda menggunakan notasi titik (Object.myMethod saya). Jika properti dideklarasikanreadonly
, tidak ada penyetel yang dibuat. Itu berarti variabel pendukung, dinamai dengan garis bawah, itu sendiri tidak hanya dapat dibaca. Thereadonly
berarti hanya bahwa ada metode setter disintesis, dan karena itu menggunakan notasi dot untuk menetapkan nilai gagal dengan kesalahan kompilator. Notasi titik gagal karena kompilator menghentikan Anda dari memanggil metode (penyetel) yang tidak ada.Cara termudah untuk menyiasatinya adalah dengan langsung mengakses variabel anggota, dinamai dengan garis bawah. Anda dapat melakukannya bahkan tanpa mendeklarasikan variabel bernama garis bawah! Xcode memasukkan deklarasi itu sebagai bagian dari proses build / compile, jadi kode yang Anda kompilasi memang akan memiliki deklarasi variabel. Tapi Anda tidak pernah melihat deklarasi itu di file kode sumber asli Anda. Bukan sihir, hanya gula sintaksis .
Menggunakan
self->
adalah cara untuk mengakses variabel anggota dari objek / instance. Anda mungkin bisa menghilangkannya, dan cukup gunakan nama var. Tapi saya lebih suka menggunakan panah + diri karena itu membuat kode saya terdokumentasi sendiri. Jika Anda melihatself->_foo
Anda tahu tanpa ambiguitas, itu_foo
adalah variabel anggota pada contoh ini.By the way, diskusi pro dan kontra dari accesor properti terhadap akses Ivar langsung adalah persis jenis pengobatan bijaksana Anda akan membaca di Dr Matt Neuberg 's Programming iOS buku. Saya merasa sangat membantu untuk membaca dan membaca ulang.
sumber
readonly
sehingga tidak ada kelas lain yang dapat menyetelnya.Cara lain yang saya temukan untuk bekerja dengan properti hanya-baca adalah dengan menggunakan @synthesize untuk menentukan penyimpanan dukungan. Sebagai contoh
Kemudian dalam implementasinya
Metode Anda kemudian dapat disetel
m_whatever
, karena ini adalah variabel anggota.Hal menarik lainnya yang saya sadari dalam beberapa hari terakhir adalah Anda dapat membuat properti hanya-baca yang dapat ditulis oleh subkelas seperti:
(di file header)
Kemudian dalam implementasinya
Ini akan menggunakan deklarasi di file header, sehingga subclass dapat memperbarui nilai properti, sambil mempertahankan keterbacaannya.
Sedikit disayangkan dalam hal penyembunyian dan enkapsulasi data.
sumber
Lihat Menyesuaikan Kelas yang Ada di iOS Docs.
Properti hanya-baca hanya memiliki metode pengambil. Anda masih dapat menyetel ivar pendukung langsung di dalam kelas properti atau menggunakan pengkodean nilai kunci.
sumber
Anda salah paham dengan pertanyaan lain. Dalam pertanyaan itu ada ekstensi kelas, yang dinyatakan sebagai berikut:
Itulah yang menghasilkan setter yang hanya terlihat dalam implementasi kelas. Jadi seperti yang dikatakan Eiko, Anda perlu mendeklarasikan ekstensi kelas dan mengganti deklarasi properti untuk memberi tahu kompilator untuk menghasilkan penyetel hanya di dalam kelas.
sumber
Solusi terpendek adalah:
MyClass.h
MyClass.h
sumber
Jika properti didefinisikan sebagai readonly, itu berarti bahwa secara efektif tidak akan ada penyetel yang dapat digunakan baik secara internal ke kelas atau secara eksternal dari kelas lain. (yaitu: Anda hanya akan memiliki "getter" jika itu masuk akal.)
Dari bunyinya, Anda menginginkan properti baca / tulis normal yang ditandai sebagai privat, yang dapat Anda capai dengan menyetel variabel kelas sebagai privat di file antarmuka Anda seperti:
sumber