Apakah Swift mendukung refleksi? misalnya apakah ada sesuatu seperti valueForKeyPath:
dan setValue:forKeyPath:
untuk objek Swift?
Sebenarnya apakah itu bahkan memiliki sistem tipe dinamis, seperti obj.class
di Objective-C?
Apakah Swift mendukung refleksi? misalnya apakah ada sesuatu seperti valueForKeyPath:
dan setValue:forKeyPath:
untuk objek Swift?
Sebenarnya apakah itu bahkan memiliki sistem tipe dinamis, seperti obj.class
di Objective-C?
Jawaban:
Sepertinya ada awal dari beberapa dukungan refleksi:
class Fruit {
var name="Apple"
}
reflect(Fruit()).count // 1
reflect(Fruit())[0].0 // "name"
reflect(Fruit())[0].1.summary // "Apple"
Dari mchambers gist, di sini: https://gist.github.com/mchambers/fb9da554898dae3e54f2
Mirror
sebenarnya mengutip kata tersebut IDE
beberapa kali.
_stdlib_getTypeName
dapat membantu.
Jika sebuah kelas diperluas NSObject
, maka semua introspeksi dan dinamisme Objective-C akan berfungsi. Ini termasuk:
Satu kekurangan dari fungsionalitas ini adalah dukungan untuk tipe nilai opsional Swift. Misalnya properti Int dapat dihitung dan dimodifikasi tetapi Int? properti tidak bisa. Jenis opsional dapat disebutkan sebagian menggunakan reflect / MirrorType, tetapi masih tidak dimodifikasi.
Jika sebuah kelas tidak diperluas NSObject
, maka hanya refleksi baru yang sangat terbatas (dan sedang dalam proses?) Yang berfungsi (lihat reflect / MirrorType), yang menambahkan kemampuan terbatas untuk menanyakan instance tentang kelas dan propertinya, tetapi tidak ada fitur tambahan di atas .
Saat tidak memperluas NSObject, atau menggunakan direktif '@objc', Swift secara default menggunakan pengiriman berbasis statis dan vtable. Ini lebih cepat, bagaimanapun, dengan tidak adanya mesin virtual tidak memungkinkan intersepsi metode runtime. Intersepsi ini merupakan bagian fundamental dari Kakao dan diperlukan untuk jenis fitur berikut:
Oleh karena itu, disarankan agar klas dalam aplikasi Cocoa / CocoaTouch diimplementasikan dengan Swift:
Ringkasan:
Data referensi: Overhead eksekusi untuk pemanggilan metode:
(kinerja sebenarnya bergantung pada perangkat keras, tetapi rasionya akan tetap sama).
Selain itu, atribut dynamic memungkinkan kita untuk secara eksplisit menginstruksikan Swift bahwa suatu metode harus menggunakan pengiriman dinamis, dan oleh karena itu akan mendukung intersepsi.
public dynamic func foobar() -> AnyObject {
}
Dokumentasi berbicara tentang sistem tipe dinamis, terutama tentang
Type
dan dynamicType
Lihat Jenis Metatype (dalam Referensi Bahasa)
Contoh:
var clazz = TestObject.self
var instance: TestObject = clazz()
var type = instance.dynamicType
println("Type: \(type)") //Unfortunately this prints only "Type: Metatype"
Sekarang dengan asumsi TestObject
meluasNSObject
var clazz: NSObject.Type = TestObject.self
var instance : NSObject = clazz()
if let testObject = instance as? TestObject {
println("yes!") //prints "yes!"
}
Saat ini, belum ada refleksi yang dilaksanakan.
EDIT: Saya ternyata salah, lihat jawaban stevex. Ada beberapa refleksi sederhana hanya baca untuk properti yang dibangun, mungkin untuk memungkinkan IDE memeriksa konten objek.
Tampaknya API refleksi Swift saat ini bukan prioritas utama Apple. Tapi selain jawaban @stevex ada fungsi lain di perpustakaan standar yang membantu.
Pada beta 6 _stdlib_getTypeName
mendapatkan nama jenis variabel yang rusak. Rekatkan ini ke taman bermain kosong:
import Foundation
class PureSwiftClass {
}
var myvar0 = NSString() // Objective-C class
var myvar1 = PureSwiftClass()
var myvar2 = 42
var myvar3 = "Hans"
println( "TypeName0 = \(_stdlib_getTypeName(myvar0))")
println( "TypeName1 = \(_stdlib_getTypeName(myvar1))")
println( "TypeName2 = \(_stdlib_getTypeName(myvar2))")
println( "TypeName3 = \(_stdlib_getTypeName(myvar3))")
Outputnya adalah:
TypeName0 = NSString
TypeName1 = _TtC13__lldb_expr_014PureSwiftClass
TypeName2 = _TtSi
TypeName3 = _TtSS
Entri blog Ewan Swick membantu menguraikan string berikut:
misalnya _TtSi
singkatan dari internal SwiftInt
tipe .
Mike Ash memiliki entri blog yang bagus yang membahas topik yang sama .
Anda mungkin ingin mempertimbangkan untuk menggunakan toString () sebagai gantinya. Ini publik dan berfungsi sama seperti _stdlib_getTypeName () dengan perbedaan bahwa itu juga berfungsi di AnyClass , misalnya di Playground enter
class MyClass {}
toString(MyClass.self) // evaluates to "__lldb_expr_49.MyClass"
Tidak ada reflect
kata kunci di Swift 5, sekarang Anda dapat menggunakan
struct Person {
var name="name"
var age = 15
}
var me = Person()
var mirror = Mirror(reflecting: me)
for case let (label?, value) in mirror.children {
print (label, value)
}
json
deserialisasi