Penggunaan inferensi Swift 3 @objc dalam mode Swift 4 sudah usang?

485

Secara singkat, saat menggunakan Xcode 9 Beta, saya telah menjalankan peringatan berikut:

Penggunaan inferensi Swift 3 @objc dalam mode Swift 4 sudah usang. Harap alamat peringatan inferensi @objc yang sudah tidak berlaku, uji coba kode Anda dengan mengaktifkan "Pencatatan inferensi Swift 3 @objc yang sudah tidak berlaku" diaktifkan, dan nonaktifkan inferensi Swift 3 @objc. **

Setelah beberapa penelitian, saya masih tidak tahu bagaimana cara memperbaiki masalah ini. Saya akan sangat menghargai tips tentang cara memperbaiki masalah ini serta penjelasan tentang apa yang sedang terjadi.

Tujuan saya adalah untuk memahami dengan lebih baik apa yang terjadi dengan kode saya.

DaleK
sumber
4
Saya tidak benar-benar mendapatkan pesan peringatan dari objek mana yang menyebabkannya. Xcode tidak mengatakan di baris mana objek itu berada. Adakah saran untuk mengetahui dari mana peringatan ini berasal?
olyv

Jawaban:

816

Saya menyingkirkan peringatan ini dengan mengubah pengaturan build "Swift 3 @objc Inference" dari target saya menjadi "Default".

Nonaktifkan inferensi Swift 3 @objc di Xcode9

Dari artikel ini :

Sebelum Swift 4, kompiler membuat beberapa deklarasi Swift secara otomatis tersedia untuk Objective-C . Misalnya, jika satu subkelas dari NSObject, kompiler membuat titik entri Objective-C untuk semua metode di kelas tersebut. Mekanisme ini disebut inferensi @objc.

Dalam Swift 4, inferensi @objc otomatis semacam itu sudah usang karena mahal untuk menghasilkan semua titik entri Objective-C. Ketika pengaturan "Swift 3 @objc Inference" diatur ke "Aktif", ini memungkinkan kode lama berfungsi. Namun, itu akan menampilkan peringatan penghentian yang perlu ditangani. Disarankan untuk "memperbaiki" peringatan ini dan mengganti pengaturan ke "Default" , yang merupakan default untuk proyek Swift baru.

Lihat juga proposal Swift ini untuk informasi lebih lanjut.

Evgenii
sumber
5
Evgenii terima kasih. Apakah ini Solusi jangka panjang?
DaleK
6
@ Bicaralah ya, saya percaya begitu. Menurut proposal Swift yang saya sebutkan dalam jawaban saya, kesimpulan objc sudah usang. Pengaturan "Swift 3 objc Inference" hanya ada dalam proyek yang dimigrasikan dari versi Swift yang lebih lama. Jika seseorang membuat proyek baru, pengaturan tidak lagi ada, yang berarti bahwa inferensi objek tidak aktif. Dianjurkan untuk mengatasi peringatan inferensi objek dan mengaturnya ke "Off".
Evgenii
4
Pesan info dalam XCode menunjukkan bahwa: "Penggunaan @objcinferensi Swift 3 dalam mode Swift 4 sudah usang. Harap alamat @objcperingatan inferensi yang tidak digunakan lagi , uji kode Anda dengan @objcmengaktifkan" inferensi Swift 3 usang "yang diaktifkan , dan nonaktifkan @objcinferensi Swift 3. " Adakah yang tahu di mana harus mengaktifkan @objclogging inferensi Swift 3 ?
courteouselk
4
@courteouselk, menurut proposal Swift, seseorang dapat mengatur SWIFT_DEBUG_IMPLICIT_OBJC_ENTRYPOINT variabel lingkungan ke nilai dari 1 hingga 3 untuk melihat penggunaan titik entri Objective-C di log.
Evgenii
14
Tambahkan saja - Anda harus melakukan ini untuk semua taget build, bukan hanya proyek.
Krivvenz
270

- Apa itu @objckesimpulan? Apa yang sedang terjadi?

Di Swift 3, kompiler menyimpulkan @objcdi sejumlah tempat sehingga Anda tidak perlu melakukannya. Dengan kata lain, itu memastikan untuk menambahkan @objcuntuk Anda!

Di Swift 4, kompiler tidak lagi melakukan ini (sebanyak). Anda sekarang harus menambahkan @objcsecara eksplisit.

Secara default, jika Anda memiliki proyek pra-Swift 4, Anda akan mendapatkan peringatan tentang ini. Dalam proyek Swift 4, Anda akan mendapatkan galat build. Ini dikontrol melalui SWIFT_SWIFT3_OBJC_INFERENCEpengaturan build. Dalam proyek pra-Swift 4 ini diatur ke On. Saya akan merekomendasikan untuk mengatur ini ke Default(atau Off), yang sekarang merupakan opsi default pada proyek baru.

Diperlukan waktu untuk mengonversi semuanya, tetapi karena ini adalah default untuk Swift 4, perlu dilakukan.

- Bagaimana saya menghentikan peringatan / kesalahan kompiler?

Ada dua cara untuk mengubah kode Anda sehingga kompiler tidak mengeluh.

Pertama adalah menggunakan @objcsetiap fungsi atau variabel yang perlu diekspos ke runtime Objective-C:

@objc func foo() {

}

Yang lain adalah dengan menggunakan @objcMembersoleh Classdeklarasi. Hal ini akan memastikan untuk secara otomatis menambahkan @objcke semua fungsi dan variabel di kelas. Ini adalah cara yang mudah, tetapi memiliki biaya, misalnya, dapat meningkatkan ukuran aplikasi Anda dengan mengekspos fungsi yang tidak perlu diekspos.

@objcMembers class Test {

}

- Apa itu @objcdan mengapa itu perlu?

Jika Anda memperkenalkan metode atau variabel baru ke kelas Swift, menandai mereka sebagai @objcmengekspos mereka ke runtime Objective-C. Ini diperlukan ketika Anda memiliki kode Objective-C yang menggunakan kelas Swift Anda, atau, jika Anda menggunakan fitur tipe Objective-C seperti Selectors. Misalnya, pola aksi target: button.addTarget(self, action:#selector(didPressButton), for:.touchUpInside)

- Mengapa saya tidak menandai semuanya @objc?

Ada negatif yang muncul dengan menandai sesuatu sebagai @objc:

  • Ukuran biner aplikasi bertambah
  • Tidak ada fungsi yang berlebihan

Harap diingat bahwa ini adalah ringkasan yang sangat tinggi dan lebih rumit daripada yang saya tulis. Saya akan merekomendasikan membaca proposal yang sebenarnya untuk informasi lebih lanjut.

Sumber:

kgaidis
sumber
@objctidak menyiratkan pengiriman dinamis, Swift bebas menggunakan pengiriman statis atau virtual (dan mungkin mengeksekusi kode yang berbeda sebagai hasilnya). Kata dynamickunci diperlukan untuk memaksa Swift menggunakan pengiriman dinamis.
kevin
7
Apakah ada cara lain untuk menambahkan aksi ke tombol? Jika @objckehilangan apa yang harus kita gunakan?
Aznix
5
@Stefan ya, mungkin ada sedikit yang harus dikonversi. Membaginya menjadi beberapa tahap. Tinggalkan SWIFT_SWIFT3_OBJC_INFERENCEdi On. Konversikan ke Swift 4. Lalu tangani @objcbarang - barang itu. Untuk membuatnya sederhana, ikuti aturan dasar: JIKA kelas Swift digunakan dalam kode Objc-C (via bridging header), gunakan @objcMembers, jika tidak, tambahkan satu-per-satu @objc. Cukup gunakan pencarian Xcode untuk mengetahui apakah kelas Swift dipanggil dari .mfile apa pun . Ini seharusnya membuat konversi relatif tidak menyakitkan.
kgaidis
5
@Berkatalah jawaban ini harus diterima. Menekan peringatan dan membuat segala sesuatunya berfungsi seperti pada Swift 3 adalah pilihan, tapi IMHO bukan yang terbaik. Sangat penting untuk memahami mengapa @objcperubahan di Swift 4 dan kemudian membuat keputusan untuk memperbaiki proyek dan tetap sama.
derpoliuk
2
Terima kasih atas penjelasan singkat ini
Schmoudi
48

Migrator tidak dapat mengidentifikasi semua fungsi yang membutuhkan @objc Inferred Objective-C thunks yang ditandai sebagai usang untuk membantu Anda menemukannya
• Membuat peringatan tentang metode yang sudah usang
• Pesan konsol saat menjalankan thunks yang sudah usang

masukkan deskripsi gambar di sini

Hassan Taleb
sumber
1
Jadi apa yang harus saya lakukan dengan @objc? Singkirkan? tinggalkan? Saya sudah menghapus itu. dan saya mendapatkan peringatan itu jadi saya harus menambahkannya? bahwa pada langkah 3 yang harus saya lakukan dengan itu?
Shial
Tambahkan @objc tepat sebelum func
Hassan Taleb
1
tentang apa langkah 3? Anda dapat menambahkan beberapa deskripsi :)
Shial
Dan dalam kasus saya, saya mendapatkan peringatan ini, tetapi tidak ada kode yang ditunjukkan. Ada dua metode yang ditandai @objc dan tampaknya hanya metode yang membutuhkannya. Saya mengubahnya ke Default dan masih mendapatkan peringatan saat kompilasi.
Maury Markowitz
12

Saya mendapat peringatan ini dengan "Swift 3 @objc Inference" = "Pengaturan default". Kemudian saya menyadari bahwa itu ditetapkan untuk Proyek - bukan untuk target. Jadi, pastikan Anda memiliki pengaturan "Default" di target Anda untuk menghilangkan peringatan.

Dmitry
sumber
Saya menyia-nyiakan 20 menit mencari untuk menyelesaikan kesalahan bahkan setelah saya mengubah ke Default dalam pengaturan proyek. Anda menunjukkan dengan tepat bahwa itu perlu diubah dalam target juga.
SkrewEverything
8

Anda cukup beralih ke "default" alih-alih "ON". Tampak lebih patuh pada logika Apple.

(tetapi semua komentar lain tentang penggunaan @objtetap valid.)

ingconti
sumber
7

Memang, Anda akan menyingkirkan peringatan itu dengan menonaktifkan Swift 3 @objc Inference. Namun, masalah halus mungkin muncul. Misalnya, KVO akan berhenti bekerja. Kode ini berfungsi dengan baik di bawah Swift 3:

for (key, value) in jsonDict {
    if self.value(forKey: key) != nil {
        self.setValue(value, forKey: key)
    }
}

Setelah bermigrasi ke Swift 4, dan menetapkan "Swift 3 @objc Inference" ke default, fitur tertentu dari proyek saya berhenti berfungsi . Butuh beberapa debug dan riset untuk menemukan solusi untuk ini. Menurut pengetahuan terbaik saya, berikut adalah pilihannya:

  • Aktifkan "Swift 3 @objc Inference" (hanya berfungsi jika Anda memigrasikan proyek yang sudah ada dari Swift 3) masukkan deskripsi gambar di sini
  • Tandai metode dan properti yang terpengaruh sebagai @objc masukkan deskripsi gambar di sini
  • Aktifkan kembali inferensi ObjC untuk seluruh kelas menggunakan @objcMembers masukkan deskripsi gambar di sini

Mengaktifkan kembali inferensi @objc memberi Anda peringatan, tetapi ini solusi tercepat. Perhatikan bahwa ini hanya tersedia untuk proyek yang dimigrasikan dari versi Swift sebelumnya. Dua opsi lainnya lebih membosankan dan memerlukan beberapa penggalian kode dan pengujian ekstensif.

Lihat juga https://github.com/apple/swift-evolution/blob/master/proposals/0160-objc-inference.md

Karoly Nyisztor
sumber
7

Saya sesekali iOS dev (segera menjadi lebih), tetapi saya masih tidak dapat menemukan pengaturan seperti yang dipandu oleh jawaban lain (karena saya tidak memiliki item Keychain yang jawabannya tampilkan), jadi sekarang saya menemukannya, saya pikir Saya mungkin menambahkan snapshot ini dengan lokasi yang disorot yang perlu Anda klik dan temukan.

  1. Mulai di kiri atas
  2. Pilih ikon folder proyek
  3. Pilih nama proyek utama Anda di bawah ikon folder proyek.
  4. Pilih Bangun Pengaturan di sisi kanan.
  5. Pilih proyek Anda di bawah TARGET.
  6. Gulir sangat jauh ke bawah (atau cari inferensi kata di kotak teks pencarian)

Menemukan pengaturan

raddevus
sumber
6

Anda dapat mencoba "Pembaruan pod" dan / atau "flutter clean"

Saya juga mengatur pengaturan ini dalam xcode.

Pengaturan antarmuka Objective-C adalah sebagai berikut:

Pengaturan antarmuka ObjectiveC

wisekiddo
sumber
2

Swift 3 @objc Inference Penggunaan inferensi Swift 3 @objc dalam mode Swift 4 sudah usang. Harap alamat peringatan inferensi @objc yang sudah tidak berlaku, uji kode Anda dengan pencatatan "Penggunaan inferensi Swift 3 @objc yang sudah usang" diaktifkan, lalu nonaktifkan inferensi dengan mengubah pengaturan build "Swift 3 @objc Inference" ke "Default" untuk "XMLParsingURL" target.

sampai ke

  1. Langkah pertama adalah Build Setting

  2. Cari di untuk Membangun Inferensi Pengaturan

  3. ubah Swift 3 @objc Inference Default

masukkan deskripsi gambar di sini

Praveen Kumar
sumber
1

Yang Anda butuhkan hanya menjalankan tes tunggu sampai selesai, setelah itu pergi ke Build Setting, Cari in untuk Build Setting Inference, ubah Swift 3 @objc Inference ke (Default). itu semua yang saya lakukan dan bekerja dengan sempurna.

Acasey
sumber
0

Penggunaan inferensi Swift 3 @objc dalam mode Swift 4 sudah usang?

gunakan func call @objc

func call(){

foo()

}

@objc func foo() {

}
Puji Wahono
sumber
0

Di atas apa yang dikatakan @wisekiddo, Anda juga dapat memodifikasi pengaturan build Anda di project.pbxprojfile dengan mengatur Swift 3 @obj Inference ke default seperti SWIFT_SWIFT3_OBJC_INFERENCE = Default;untuk rasa build Anda (yaitu debug dan lepaskan), terutama jika Anda berasal dari lingkungan lain selain Xcode

DaveNOTDavid
sumber