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?

Jean Lebrument
sumber
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 {

}
Jamie Forrest
sumber
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.

Pelle Stenild Coltau
sumber
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

Chris Nolet
sumber
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
1
Tautan yang sama tersedia melalui WebArchive: web.archive.org/web/20170310053717/https://developer.apple.com/…
Richard Topchii
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();
}
Michal
sumber
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>
Vinay Hosamane
sumber
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