Jika demikian, adakah perbedaan utama yang tidak ada ketika menggunakan observasi nilai kunci di Objective-C?
swift
key-value-observing
codeperson
sumber
sumber
.initial
. Untuk solusinya lihat di sini . Saya sangat merekomendasikan untuk melihat dokumen Apple . Sudah diperbarui baru-baru ini dan mencakup banyak catatan penting. Lihat juga jawabanJawaban:
(Diedit untuk menambahkan info baru): pertimbangkan apakah menggunakan kerangka kerja Combine dapat membantu Anda mencapai apa yang Anda inginkan, daripada menggunakan KVO
Iya dan tidak. KVO bekerja pada subclass NSObject seperti biasanya. Ini tidak berfungsi untuk kelas yang tidak mensubk NSObject. Swift tidak (saat ini setidaknya) memiliki sistem pengamatan asli sendiri.
(Lihat komentar untuk cara mengekspos properti lain sebagai ObjC sehingga KVO bekerja pada mereka)
Lihat Dokumentasi Apple untuk contoh lengkap.
sumber
dynamic
kata kunci pada kelas Swift apa saja untuk mengaktifkan dukungan KVO.dynamic
kata kunci berada di properti yang Anda ingin membuat nilai kunci dapat diamati.dynamic
kata kunci dapat ditemukan di Menggunakan Perpustakaan Swift Apple Library dengan bagian Kakao dan Objective-C .dynamic
kata kunci untuk properti apa pun di dalam kelas yang ingin Anda patuhi KVO (bukandynamic
kata kunci pada kelas itu sendiri). Ini berhasil untuk saya!Anda dapat menggunakan KVO di Swift, tetapi hanya untuk
dynamic
propertiNSObject
subclass. Pertimbangkan bahwa Anda ingin mengamatibar
propertiFoo
kelas. Di Swift 4, tentukanbar
sebagaidynamic
properti diNSObject
subkelas Anda :Anda kemudian dapat mendaftar untuk mengamati perubahan pada
bar
properti. Dalam Swift 4 dan Swift 3.2, ini telah sangat disederhanakan, seperti diuraikan dalam Menggunakan Pengamatan Nilai-Kunci di Swift :Catatan, dalam Swift 4, kita sekarang memiliki pengetikan keypath yang kuat menggunakan karakter backslash (
\.bar
adalah keypath untukbar
properti objek yang diamati). Juga, karena menggunakan pola penutupan penyelesaian, kita tidak harus menghapus pengamat secara manual (ketikatoken
jatuh di luar ruang lingkup, pengamat dihapus untuk kita) juga tidak perlu khawatir tentang memanggilsuper
implementasi jika kuncinya tidak pertandingan. Penutupan ini dipanggil hanya ketika pengamat khusus ini dipanggil. Untuk informasi lebih lanjut, lihat video WWDC 2017, What's New in Foundation .Dalam Swift 3, untuk mengamati ini, ini sedikit lebih rumit, tetapi sangat mirip dengan apa yang dilakukan di Objective-C. Yaitu, Anda akan mengimplementasikan
observeValue(forKeyPath keyPath:, of object:, change:, context:)
yang mana (a) memastikan kita berurusan dengan konteks kita (dan bukan sesuatu yangsuper
terdaftar untuk diamati oleh contoh kita ); dan kemudian (b) menanganinya atau meneruskannya kesuper
implementasi, sebagaimana diperlukan. Dan pastikan untuk melepaskan diri Anda sebagai pengamat saat yang tepat. Misalnya, Anda dapat menghapus pengamat saat itu tidak dialokasikan:Dalam Swift 3:
Catatan, Anda hanya bisa mengamati properti yang bisa direpresentasikan dalam Objective-C. Dengan demikian, Anda tidak dapat mengamati obat generik,
struct
tipe Swiftenum
, tipe Swift , dll.Untuk diskusi tentang implementasi Swift 2, lihat jawaban asli saya, di bawah ini.
Menggunakan
dynamic
kata kunci untuk mencapai KVO denganNSObject
subkelas dijelaskan di bagian Pengamatan Nilai-Kunci pada bab Mengadopsi Konvensi Desain Kakao dari Menggunakan Swift dengan Kakao dan panduan Objective-C :[Catatan, diskusi KVO ini kemudian telah dihapus dari panduan Menggunakan Swift dengan Kakao dan Objective-C , yang telah diadaptasi untuk Swift 3, tetapi masih berfungsi seperti yang dijabarkan di bagian atas jawaban ini.]
Perlu dicatat bahwa Swift memiliki sistem pengamat properti asli sendiri , tetapi itu untuk kelas yang menetapkan kode sendiri yang akan dilakukan setelah mengamati propertinya sendiri. KVO, di sisi lain, dirancang untuk mendaftar untuk mengamati perubahan pada beberapa properti dinamis dari beberapa kelas lain.
sumber
myContext
dan bagaimana Anda mengamati beberapa properti?context
pointer.context
Pointer diberikan kepada pengamat ketikaobserveValueForKeyPath:ofObject:change:context:
dipanggil.context
Pointer dapat berupa pointer C atau referensi objek.context
Pointer dapat berupa digunakan sebagai pengidentifikasi unik untuk menentukan perubahan yang sedang diamati, atau untuk memberikan beberapa data lain kepada pengamat. "options
kosong, itu hanya berarti bahwachange
tidak akan menyertakan nilai lama atau baru (mis. Anda mungkin mendapatkan sendiri nilai baru dengan mereferensikan objek itu sendiri). Jika Anda hanya menentukan.new
dan tidak.old
, itu berarti bahwachange
hanya akan memasukkan nilai baru, tetapi bukan nilai lama (misalnya Anda sering tidak peduli tentang apa nilai lama itu, tetapi hanya peduli tentang nilai baru). Jika Anda harusobserveValueForKeyPath
memberi Anda nilai lama dan baru, maka tentukan[.new, .old]
. Intinya,options
cukup tentukan apa yang termasuk dalamchange
kamus.Baik ya dan tidak:
Ya , Anda bisa menggunakan KVO API lama yang sama di Swift untuk mengamati objek Objective-C.
Anda juga dapat mengamati
dynamic
properti objek Swift yang diwarisi darinyaNSObject
.Tapi ... Tidak, itu tidak diketik seperti yang Anda harapkan dari sistem observasi asli Swift.
Menggunakan Swift dengan Kakao dan Objective-C | Mengamati Nilai Kunci
Tidak , saat ini tidak ada sistem observasi nilai bawaan untuk objek Swift yang arbitrer.
Ya , ada Pengamat Properti bawaan , yang sangat diketik.
Tapi ... Tidak, mereka bukan KVO, karena hanya memungkinkan untuk mengamati properti milik objek, tidak mendukung pengamatan bersarang ("jalur utama"), dan Anda harus mengimplementasikannya secara eksplisit.
Bahasa Pemrograman Swift | Pengamat Properti
Ya , Anda dapat menerapkan pengamatan nilai eksplisit, yang akan diketik dengan kuat, dan memungkinkan untuk menambahkan beberapa penangan dari objek lain, dan bahkan mendukung nesting / "jalur kunci".
Tapi ... Tidak itu tidak akan KVO karena hanya akan bekerja untuk properti yang Anda terapkan sebagai diamati.
Anda dapat menemukan perpustakaan untuk menerapkan mengamati nilai tersebut di sini:
Observable-Swift - KVO for Swift - Value Observing and Events
sumber
Contoh mungkin membantu sedikit di sini. Jika saya memiliki instance
model
kelasModel
dengan atributname
danstate
saya dapat mengamati atribut tersebut dengan:Perubahan pada properti ini akan memicu panggilan ke:
sumber
Iya.
KVO membutuhkan pengiriman dinamis, jadi Anda hanya perlu menambahkan
dynamic
pengubah ke metode, properti, subskrip, atau inisialisasi:dynamic var foo = 0
The
dynamic
Memastikan pengubah bahwa referensi untuk deklarasi akan secara dinamis dikirim dan diakses melaluiobjc_msgSend
.sumber
Selain jawaban Rob. Kelas itu harus diwarisi dari
NSObject
, dan kami memiliki 3 cara untuk memicu perubahan propertiGunakan
setValue(value: AnyObject?, forKey key: String)
dariNSKeyValueCoding
Gunakan
willChangeValueForKey
dandidChangeValueForKey
dariNSKeyValueObserving
Gunakan
dynamic
. Lihat Kompatibilitas Jenis SwiftDan pengambil properti dan penyetel dipanggil saat digunakan. Anda dapat memverifikasi ketika bekerja dengan KVO. Ini adalah contoh dari properti yang dihitung
sumber
Gambaran
Dimungkinkan untuk menggunakan
Combine
tanpa menggunakanNSObject
atauObjective-C
Ketersediaan:
iOS 13.0+
,macOS 10.15+
,tvOS 13.0+
,watchOS 6.0+
,Mac Catalyst 13.0+
,Xcode 11.0+
Catatan: Perlu digunakan hanya dengan kelas bukan dengan tipe nilai.
Kode:
Versi Swift: 5.1.2
Keluaran:
Lihat:
sumber
Saat ini Swift tidak mendukung mekanisme bawaan untuk mengamati perubahan properti objek selain 'diri', jadi tidak, itu tidak mendukung KVO.
Namun, KVO adalah bagian mendasar dari Objective-C dan Cocoa sehingga sangat mungkin untuk ditambahkan di masa depan. Dokumentasi saat ini tampaknya menyiratkan ini:
Menggunakan Swift dengan Kakao dan Objective-C
sumber
Satu hal penting untuk disebutkan adalah bahwa setelah memperbarui Xcode Anda ke 7 beta Anda mungkin mendapatkan pesan berikut: "Metode tidak menimpa metode apa pun dari superclass-nya" . Itu karena opsionalitas argumen. Pastikan pawang pengamatan Anda terlihat persis seperti berikut:
sumber
Ini mungkin bermanfaat bagi beberapa orang -
Saya telah menggunakan KVO dengan cara ini di Swift 3. Anda dapat menggunakan kode ini dengan beberapa perubahan.
sumber
Contoh lain bagi siapa saja yang mengalami masalah dengan jenis seperti Int? dan CGFloat ?. Anda cukup mengatur kelas Anda sebagai subkelas NSObject dan mendeklarasikan variabel Anda sebagai berikut, misalnya:
sumber