Bisakah kode objektif-c memanggil ekstensi cepat di Kelas?

94

Saya mencari beberapa posting, saya pikir saya tidak dapat menulis ekstensi di bawah swift, dan menyebutnya dari kode Objective-C, bukan?

@objc seperti atribut hanya mendukung metode, kelas, protokol?

sprhawk
sumber
1
Mengapa Anda tidak mencobanya?
HAS
7
ide mengeluh error, tapi saya ingin mendapatkan jawaban yang pasti.
sprhawk

Jawaban:

84

Anda dapat menulis ekstensi Swift dan menggunakannya dalam kode Objective-C. Diuji dengan XCode 6.1.1.

Yang perlu Anda lakukan hanyalah:

  • buat ekstensi Anda di Swift (tanpa @objcanotasi)

  • #import "ProjectTarget-Swift.h" di kelas Objective-C Anda (di mana "ProjectTarget" mewakili target XCode yang terkait dengan ekstensi Swift)

  • memanggil metode dari ekstensi Swift

Pembaruan: Seperti yang disebutkan @Rizwan Ahmed, Anda perlu menambahkan @objcanotasi:

Mulai dari Swift 4.0.3, anotasi @objc diperlukan jika Anda ingin menggunakan ekstensi dalam file kelas Objective C.

marius bardan
sumber
6
Saya telah melakukan persis seperti ini tetapi ini masih merupakan kesalahan waktu kompilasi. Hmmm. EDIT: Saya mengimpor header bridging saya, bukan "ProjectTarget-Swift.h". Der.
Jason Renaldo
Keduanya adalah header penghubung. Perbedaannya adalah yang satu untuk menggunakan kode Swift di ObjC dan yang lainnya untuk menggunakan kode ObjC di Swift. Header Swift tidak terlihat. Yang lainnya, harus Anda kelola.
marius bardan
William Hu, lihat jawaban mclaughlinj!
appleitung
39
Mulai dari Swift 4.0.3, anotasi @objc diperlukan jika Anda ingin menggunakan ekstensi dalam file kelas Objective C.
Rizwan Ahmed
69

Saya menemukan bahwa di Swift 4.0 saya harus menambahkan @objcdi depan kata kunci ekstensi saya agar metode ekstensi Swift menjadi terlihat oleh contoh kelas Objc yang saya perluas.

Pendeknya:

Pengaturan konfigurasi file:

CustomClass.h
CustomClass.m
CustomClassExtension.swift

Di CustomClassExtension:

@objc extension CustomClass
{
    func method1() 
    {
        ...
    }
}

Di AppDelegate.m saya:

self.customClass = [[CustomClass alloc] init];
[self.customClass method1];
Andrey P.
sumber
2
Jika suatu metode menggunakan generik, metode itu tidak dapat digunakan oleh Objective-C dan Anda harus menambahkan @nonobjcanotasi.
ThomasW
Sekadar catatan kecil, @objcMembers tidak berfungsi dalam kasus ini. Tidak tahu kenapa .. :-(
Raunak
46

Solusi ini berfungsi untuk Swift 2.2 dan Swift 3 . Perhatikan bahwa hanya ekstensi untuk kelas (bukan untuk struct atau enum) yang dapat diakses dari Objective-C.

import UIKit

extension UIColor {

    //Custom colours
    class func otherEventColor() -> UIColor {
        return UIColor(red:0.525, green:0.49, blue:0.929, alpha:1)
    }
}

Kemudian #import "ProductModuleName-Swift.h" di file ObjC Anda.

Cepat 4

extension UIColor {

    // As of Swift 4.0.3, the @objc annotation is needed if you want to use the extension in Objective-C files
    @objc
    class func otherEventColor() -> UIColor {
        return UIColor(red:0.525, green:0.49, blue:0.929, alpha:1)
    }
}
Foti Dim
sumber
Ini bukan "YourProjectsNameHere ..." melainkan "YourT TargetNameHere ...": untuk berbagi target, Anda harus menguncinya ke nama: dr2050.postach.io/post/…
Dan Rosenstark
1
@DanRosenark Anda benar. Saya mengubahnya menjadi "ProductModuleName-Swift.h" seperti yang disarankan Apple: developer.apple.com/library/ios/documentation/Swift/Conceptual/…
Foti Dim
1
Bekerja dengan baik untuk kecepatan 3.
Viktor Kucera
Apakah ada alasan mengapa Anda mengatakan publicdibutuhkan? Berfungsi dengan baik tanpa publicpengubah untuk saya. Apakah kita mengasumsikan bahwa ekstensi tersebut tidak ada dalam proyek yang sama tetapi diimpor dari proyek lain?
Lee Kang
Apakah saya perlu menggunakan header bridging?
jegadeesh
42

Seperti yang tercakup dalam jawaban lain, mengimpor tajuk Swift yang dihasilkan berfungsi dalam banyak kasus .

Pengecualian untuk ini adalah ketika kategori didefinisikan pada tipe yang dijembatani (yaitu ekstensi didefinisikan pada Stringdan tidak NSString). Kategori ini tidak akan secara otomatis dihubungkan ke rekan Objective-C mereka. Untuk menyiasatinya, Anda harus menggunakan tipe Objective-C (dan memasukkan nilai yang dikembalikan dalam kode Swift Anda dengan as String) atau menentukan ekstensi untuk tipe Swift dan Objective-C.

mclaughlinj.dll
sumber
2
Menambah jawaban di atas, Anda harus membuat ekstensi swift Anda publik dan mengatur tipenya sebagai NSString mis public extension NSString. Jika Anda mendapatkan pengenal yang belum terselesaikan atau kesalahan serupa pada waktu kompilasi, Anda dapat mentransmisikan kembali ke String misalnya let sVal = self as Stringdan kemudian memanggil kode yang diperlukan disVal
RunLoop
@RunLoop sebenarnya Anda tidak membutuhkan publik, ini akan bekerja tanpa penentu cakupan. Dan itu (ekspor ke Obj-C, maksud saya) tidak berfungsi untuk Strings, karena mereka adalah struct, bukan kelas dan hanya tersedia dari Swift. Jadi, ya - Anda dapat menulis ekstensi untuk NSString dan menggunakan cast, atau menulis ekstensi, seperti yang mclaughlinjdikatakan, untuk kelas NSString dan String struct
Alex Nazarsky
3

Impor header "#import" ProductModuleName-Swift.h " di file objektif-c dan tambahkan @objc di depan ekstensi Anda di file swift. Ini akan berfungsi dengan baik di Swift 4.2 dan Swift 5

Ranjani
sumber