Swift sendiri tidak menggunakan penyeleksi - beberapa pola desain yang di Objective-C memanfaatkan penyeleksi bekerja berbeda di Swift. (Misalnya, gunakan rantai tambahan pada jenis protokol atau is/ aspengujian alih-alih respondsToSelector:, dan gunakan penutupan di mana pun Anda bisa, bukan performSelector:untuk keamanan jenis / memori yang lebih baik.)
Tetapi masih ada sejumlah API berbasis ObjC penting yang menggunakan penyeleksi, termasuk penghitung waktu dan pola sasaran / tindakan. Swift menyediakan Selectortipe untuk bekerja dengannya. (Swift secara otomatis menggunakan ini sebagai pengganti SELtipe ObjC .)
Di Swift 2.2 (Xcode 7.3) dan yang lebih baru (termasuk Swift 3 / Xcode 8 dan Swift 4 / Xcode 9):
Anda bisa membuat Selectordari tipe fungsi Swift menggunakan #selectorekspresi.
let timer = Timer(timeInterval: 1, target: object,
selector: #selector(MyClass.test),
userInfo: nil, repeats: false)
button.addTarget(object, action: #selector(MyClass.buttonTapped),
for: .touchUpInside)
view.perform(#selector(UIView.insertSubview(_:aboveSubview:)),
with: button, with: otherButton)
Hal hebat tentang pendekatan ini? Referensi fungsi diperiksa oleh kompiler Swift, sehingga Anda dapat menggunakan #selectorekspresi hanya dengan pasangan kelas / metode yang benar-benar ada dan memenuhi syarat untuk digunakan sebagai penyeleksi (lihat "Ketersediaan pemilih" di bawah). Anda juga bebas membuat referensi fungsi Anda hanya sespesifik yang Anda butuhkan, sesuai aturan Swift 2.2+ untuk penamaan tipe fungsi .
(Ini sebenarnya merupakan perbaikan dari @selector()arahan ObjC , karena pemeriksaan kompiler -Wundeclared-selectorhanya memverifikasi bahwa ada pemilih bernama. Referensi fungsi Swift yang Anda berikan untuk #selectormemeriksa keberadaan, keanggotaan dalam kelas, dan ketik tanda tangan.)
Ada beberapa peringatan tambahan untuk referensi fungsi yang Anda sampaikan ke #selectorekspresi:
- Beberapa fungsi dengan nama dasar yang sama dapat dibedakan dengan label parameternya menggunakan sintaksis yang disebutkan di atas untuk referensi fungsi (misalnya
insertSubview(_:at:)vs insertSubview(_:aboveSubview:)). Tetapi jika suatu fungsi tidak memiliki parameter, satu-satunya cara untuk mendamaikannya adalah dengan menggunakan asgips dengan tanda tangan tipe fungsi (misalnya foo as () -> ()vs foo(_:)).
- Ada sintaks khusus untuk pasangan pengambil / penyetel properti di Swift 3.0+. Misalnya, diberi
var foo: Int, Anda dapat menggunakan #selector(getter: MyClass.foo)atau #selector(setter: MyClass.foo).
Catatan umum:
Kasus di mana #selectortidak berfungsi, dan penamaan: Terkadang Anda tidak memiliki referensi fungsi untuk membuat pemilih dengan (misalnya, dengan metode yang terdaftar secara dinamis di runtime ObjC). Dalam kasus itu, Anda bisa membuat a Selectordari string: misalnya Selector("dynamicMethod:")- meskipun Anda kehilangan pemeriksaan validitas kompilator. Ketika Anda melakukannya, Anda harus mengikuti aturan penamaan ObjC, termasuk titik dua ( :) untuk setiap parameter.
Ketersediaan pemilih : Metode yang dirujuk oleh pemilih harus diekspos ke runtime ObjC. Dalam Swift 4, setiap metode yang diekspos ke ObjC harus memiliki deklarasi diawali dengan @objcatribut. (Dalam versi sebelumnya Anda mendapatkan atribut itu secara gratis dalam beberapa kasus, tetapi sekarang Anda harus mendeklarasikannya secara eksplisit.)
Ingatlah bahwa privatesimbol tidak terkena runtime juga - metode Anda harus memiliki setidaknya internalvisibilitas.
Jalur utama: Ini terkait tetapi tidak persis sama dengan penyeleksi. Ada sintaks khusus untuk ini di Swift 3, juga: misalnya chris.valueForKeyPath(#keyPath(Person.friends.firstName)). Lihat SE-0062 untuk detailnya. Dan lebih banyak lagi KeyPathhal-hal di Swift 4 , jadi pastikan Anda menggunakan API berbasis KeyPath yang tepat dan bukan penyeleksi jika perlu.
Anda dapat membaca lebih lanjut tentang penyeleksi di bawah Berinteraksi dengan Objective-C APIs dalam Menggunakan Swift dengan Cocoa dan Objective-C .
Catatan: Sebelum Swift 2.2, Selectorsesuaikan dengan StringLiteralConvertible, jadi Anda mungkin menemukan kode lama tempat string kosong diteruskan ke API yang mengambil pemilih. Anda akan ingin menjalankan "Konversi ke Sintaks Swift Saat Ini" di Xcode untuk mendapatkannya #selector.
selector: test()akan memanggiltestdan meneruskannya mengembalikan nilai keselectorargumen.