Meskipun saya pikir saya bisa menjawab pertanyaan Anda, itu bukan jawaban yang Anda sukai.
TL; DR: @objc
fungsi saat ini mungkin tidak ada dalam ekstensi protokol. Anda dapat membuat kelas dasar sebagai gantinya, meskipun itu bukan solusi yang ideal.
Ekstensi Protokol dan Objective-C
Pertama, pertanyaan / jawaban ini ( Can Swift Method Defined on Extensions on Protocols Accessed in Objective-c ) tampaknya menyarankan bahwa karena cara ekstensi protokol dikirim di bawah tenda, metode yang dideklarasikan dalam ekstensi protokol tidak terlihat oleh objc_msgSend()
fungsi tersebut, dan oleh karena itu tidak terlihat oleh kode Objective-C. Karena metode yang Anda coba tentukan dalam ekstensi Anda harus terlihat oleh Objective-C (sehingga Anda UIKit
dapat menggunakannya), ia berteriak pada Anda untuk tidak menyertakannya @objc
, tetapi begitu Anda memasukkannya, ia akan berteriak kepada Anda karena@objc
tidak diizinkan di ekstensi protokol. Ini mungkin karena ekstensi protokol saat ini tidak dapat dilihat oleh Objective-C.
Kita juga dapat melihat bahwa pesan kesalahan setelah kita menambahkan @objc
status "@objc hanya dapat digunakan dengan anggota kelas, protokol @objc, dan ekstensi konkret kelas." Ini bukan kelas; ekstensi ke protokol @objc tidak sama dengan definisi protokol itu sendiri (yaitu dalam persyaratan), dan kata "konkret" akan menyarankan bahwa ekstensi protokol tidak dihitung sebagai ekstensi kelas yang konkret.
Solusi
Sayangnya, ini cukup banyak mencegah Anda dari menggunakan ekstensi protokol ketika implementasi default harus terlihat oleh kerangka kerja Objective-C. Pada awalnya, saya pikir mungkin @objc
tidak diizinkan dalam ekstensi protokol Anda karena Swift Compiler tidak dapat menjamin bahwa tipe yang sesuai akan menjadi kelas (meskipun Anda telah menentukannya secara khusus UIViewController
). Jadi saya memasang class
persyaratan P1
. Ini tidak berhasil.
Mungkin satu-satunya solusi adalah dengan hanya menggunakan kelas dasar daripada protokol di sini, tetapi ini jelas tidak sepenuhnya ideal karena kelas mungkin hanya memiliki satu kelas dasar tetapi sesuai dengan beberapa protokol.
Jika Anda memilih untuk mengikuti rute ini, harap pertimbangkan pertanyaan ini ( Metode Protokol Opsional ObjC Swift 3 Tidak Disebut dalam Subkelas ) ke dalam akun. Tampaknya masalah lain saat ini di Swift 3 adalah bahwa subclass tidak secara otomatis mewarisi implementasi persyaratan protokol opsional dari superclass mereka. Jawaban atas pertanyaan tersebut menggunakan adaptasi khusus @objc
untuk menyiasatinya.
Melaporkan Masalah
Saya pikir ini sudah dibahas di antara mereka yang mengerjakan proyek sumber terbuka Swift, tetapi Anda dapat yakin mereka mengetahuinya dengan menggunakan Reporter Bug Apple , yang kemungkinan pada akhirnya akan menuju ke Tim Inti Swift, atau reporter bug Swift . Namun, salah satu dari ini mungkin menganggap bug Anda terlalu luas atau sudah diketahui. Tim Swift juga dapat menganggap apa yang Anda cari sebagai fitur bahasa baru, dalam hal ini Anda harus memeriksa milis terlebih dahulu .
Memperbarui
Pada Desember 2016, masalah ini dilaporkan ke komunitas Swift. Masalah tersebut masih ditandai sebagai terbuka dengan prioritas menengah, tetapi komentar berikut telah ditambahkan:
Ini dimaksudkan. Tidak ada cara untuk menambahkan implementasi metode ke setiap pengguna, karena ekstensi dapat ditambahkan setelah kesesuaian dengan protokol. Saya kira kami dapat mengizinkannya jika ekstensi berada dalam modul yang sama dengan protokol.
Karena protokol Anda berada dalam modul yang sama dengan ekstensi Anda, bagaimanapun, Anda mungkin dapat melakukan ini di versi Swift yang akan datang.
Perbarui 2
Pada bulan Februari 2017, masalah ini secara resmi ditutup sebagai "Won't Do" oleh salah satu anggota Swift Core Team dengan pesan berikut:
Ini disengaja: ekstensi protokol tidak dapat memasukkan titik masuk @objc karena keterbatasan runtime Objective-C. Jika Anda ingin menambahkan titik masuk @objc ke NSObject, perpanjang NSObject.
Memperluas NSObject
atau bahkan UIViewController
tidak akan mencapai apa yang Anda inginkan, tetapi sayangnya tampaknya tidak akan menjadi mungkin.
Di masa depan (yang sangat) panjang, kami mungkin dapat menghilangkan ketergantungan pada @objc
metode sepenuhnya, tetapi waktu itu kemungkinan besar tidak akan datang dalam waktu dekat karena kerangka kerja Cocoa saat ini tidak ditulis di Swift (dan tidak bisa sampai memiliki ABI yang stabil) .
Perbarui 3
Mulai Musim Gugur 2019, ini menjadi lebih sedikit masalah karena semakin banyak kerangka kerja Apple yang ditulis di Swift. Misalnya, jika Anda menggunakan SwiftUI
alih-alih UIKit
, Anda menghindari masalah sepenuhnya karena @objc
tidak akan pernah diperlukan saat merujuk ke suatu SwiftUI
metode.
Kerangka kerja Apple yang ditulis di Swift meliputi:
- SwiftUI
- RealityKit
- Menggabungkan
- CryptoKit
Orang akan berharap pola ini berlanjut seiring waktu karena Swift secara resmi ABI dan modul stabil pada Swift 5.0 dan 5.1, masing-masing.
@objc