Mengimpor protokol Swift di kelas Objective-C


116

Saya mencoba mengimpor Protokol Swift bernama AnalyticProtocolke dalam kelas Objective-C bernama AnalyticFactory.

protocol AnalyticProtocol
{

}

Saya memulai dari proyek Objective-C yang sudah ada (saya tidak membuat proyek Swift baru dengan xCode dan saya tidak menemukan cara mengkonfigurasi proyek Objective-C saya menjadi proyek Swift di xCode 6 ).

Di file Swift saya, saya menyertakan .hfile bernama MyProjectName-Swift.htetapi compiler mengembalikan saya kesalahan yang memberi tahu saya bahwa itu tidak ada . Jadi, saya membuat .hfile bernama MyProjectName-Swift.hyang sebenarnya kosong (saya tidak tahu apa yang harus saya masukkan ke dalamnya).

Dalam dokumentasi Apple mereka mengatakan bahwa saya harus menyertakan .hfile saya yang diberi nama MyProjectName-Swift.hdi .mfile saya . Tapi saya perlu memasukkannya bukan ke .mfile saya, tetapi ke file saya .h. Apakah ini bisa menjadi masalah?

Ketika saya mencoba untuk mengkompilasi, saya mendapat kesalahan ini :: 0: error: xxxAnalyticFactory.h: 39: tidak dapat menemukan deklarasi protokol untuk 'AnalyticProtocol'

Dan kode yang memberatkan:

@interface AnalyticFactory : NSObject
{
    Class<AnalyticProtocol> _analyticProtocolClass; // The type of the analytic class currently used.
}

Saya rasa saya tidak mengerti dengan baik bagaimana saya bisa mengimpor protokol Swift ke dalam kelas Objective-C.

Apakah ada yang melihat kesalahan dalam apa yang saya lakukan?


Lihat video Mengintegrasikan Swift Dengan Objective-C dari WWDC 2014. Sekitar pukul 30:40 ke dalam video, mereka menjelaskan cara mengakses protokol Swift di kelas Objective-C.
Jamie Forrest

Jawaban:


224

Anda perlu menambahkan @objcatribut ke protokol Swift Anda seperti ini:

@objc protocol AnalyticProtocol {

}

25
Terima kasih atas jawaban Anda tetapi masalahnya masih berlanjut.
Jean Lebrument

Bisakah Anda memposting proyek sampel yang mereproduksi masalah?
Jamie Forrest

Menambahkan @objc membantu saya mengimpor kelas Swift ke Obj-C
serg

19
@objc tidak selalu berhasil. Ketika sesuai dengan protokol kadang-kadang tidak bekerja saat menambahkan protokol di @interfacedalam .hberkas. namun, Anda dapat menambahkan protokol ke privat @interfacedalam .mfile dan memperbaiki banyak hal (setidaknya kadang-kadang terjadi pada saya). Jadi di atas yang Anda @implementationmiliki @interface MyController() <AnalyticProtocol>.
Adam

1
Terkadang Xcode 8 akan mengeluh saat Anda mengedit, tetapi ketika Anda benar-benar membuatnya, mengikuti jawaban ini bersama dengan komentar, kesalahannya akan hilang.
Roger Pingleton

77

Tidak mungkin mengimpor header Swift yang dibuat Xcode dalam file header objC.

Jadi, karena Anda ingin menggunakan kode Swift dalam file header objC, Anda perlu "meneruskan deklarasi" kelas dan protokol yang ingin Anda gunakan dalam file header objC, seperti ini:

@protocol AnalyticProtocol;

Anda sekarang dapat menggunakan protokol dalam deklarasi kelas objC Anda:

@interface AnalyticFactory : NSObject
{
    Class<AnalyticProtocol> _analyticProtocolClass; // The type of the analytic class currently used.
}

Dalam file implementasi Anda (file objC .m), Anda dapat mengimpor file header Swift ("ProductModuleName-Swift.h") yang dihasilkan Xcode dan implementasi yang benar AnalyticProtocolsekarang akan diketahui oleh compiler.

Ini juga dijelaskan di bagian "Menggunakan Swift dari Objective-C" di Apple Docs

Perhatikan bahwa XCode akan memberikan peringatan di file header objC ketika Anda menggunakan protokol yang dideklarasikan ke depan ("Tidak dapat menemukan definisi protokol untuk 'AnalyticProtocol'), tetapi ini dapat diabaikan - implementasi akan ditemukan pada waktu kompilasi.


19
Mengapa Xcode menampilkan peringatan untuk protokol yang hilang saat dikompilasi dan berfungsi dengan baik? Adakah cara untuk menghapus peringatan?
Oren

Meskipun demikian, tetap tidak mungkin untuk memanggil metode protokol pada kelas ini. Ini akan memberikan kesalahanNo visible @interface for <ClassName> declares the selector <protocolMethodName>
Elsa

itu menghasilkan peringatan berikut: "Tidak dapat menemukan definisi protokol untuk xxxx"
JAHelia

51

Bagi siapa saja yang hanya perlu mengadopsi protokol - Anda dapat melakukannya dalam dua langkah, tanpa menimbulkan peringatan atau kesalahan:

  1. Di .swiftfile Anda , tambahkan @objcsebelum nama protokol:

    @objc protocol AnalyticProtocol {
    
    }
  2. Di .mfile Anda , impor header Swift yang dihasilkan dan adopsi protokol dalam kategori pribadi. (File header dinamai secara otomatis):

    #import "ProductModuleName-Swift.h"
    
    @interface AnalyticFactory () <AnalyticProtocol>
    
    @end

Ini adalah pendekatan yang direkomendasikan Apple. Anda dapat mempelajari lebih lanjut tentang mencampur dan mencocokkan Objective-C dan Swift di sini: https://developer.apple.com/library/content/documentation/Swift/Conceptual/BuildingCocoaApps/MixandMatch.html


1
Saya masih mendapat peringatan, dengan deklarasi maju atau tanpa. Saya menggunakan protokol dalam sebuah ekstensi.
Cristi Băluță

Tidak dapat mengimpor #import "AnalyticProtocol-Swift.h". Sepertinya AnyProtocol-Swift.h tidak dibuat secara otomatis seperti yang Anda katakan.
Hlung

2
Ini berhasil untuk saya; tidak ada saran atau jawaban lain di halaman ini yang berhasil. Saya menggunakan Swift 4.
Poulsbo

1
Ini adalah satu-satunya cara untuk menghapus peringatan (meskipun berfungsi ketika protokol ada di file header)
David P


3

Jika Anda membuat kerangka kerja, impor yang diperlukan

#import "ProductModuleName-Swift.h"

berubah menjadi:

#import <ProductModuleName/ProductModuleName-Swift.h>

Dalam hal ini Anda juga harus membuat protokol swift menjadi publik :

@objc public protocol AnalyticProtocol {
  func something();
}

3

Kita dapat menggunakan protokol swift di Objective C dengan sedikit perubahan pada kode. Selain itu, dengan protokol yang dideklarasikan @objc memungkinkan Anda memiliki metode opsional dan wajib tanpa implementasi default. Itu datang dengan pro dan kontra.

Kami sebenarnya dapat menamai ulang nama protokol menjadi lebih deskriptif saat menggunakan di Objective C. Saya menggunakan "@objc (alias_name)".

Ini kodenya, Mari kita memiliki protokol cepat dengan atribut @objc dan nama alias untuk digunakan dalam kode ObjC.

@objc(ObjTableViewReloadable) protocol TableViewReloadable: class {
   func reloadRow(at index: IndexPath)
   func reloadSection(at index: Int)
   func reloadTable()
}

Sekarang mari farword mendeklarasikan protokol kita dalam file .h

@protocol ObjTableViewReloadable;

Sekarang Anda dapat mengikuti protokol ini dalam file .m dan menambahkan implementasi metode yang diperlukan.

#import "MyApp-Swift.h"
@interface MyObjcViewController () <ObjTableViewReloadable>

Terima kasih telah memposting ini. Saya melihat kode warisan yang lebih tua dari kotoran dan jika pendekatan ini berhasil, itu akan menyelamatkan saya dari rasa sakit. :)
Adrian
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.