Apakah mungkin menggunakan Enum Swift di Obj-C?


144

Saya mencoba mengubah beberapa kelas Obj-C saya menjadi Swift. Dan beberapa kelas Obj-C lainnya masih menggunakan enum di kelas yang dikonversi. Saya mencari di Dokumen Pra-Rilis dan tidak dapat menemukannya atau mungkin saya melewatkannya. Apakah ada cara untuk menggunakan Swift enum di Obj-C Class? Atau tautan ke dokumen masalah ini?

Ini adalah bagaimana saya mendeklarasikan enum saya dalam kode Obj-C lama dan kode Swift baru saya.

Kode Obj-C lama saya:

typedef NS_ENUM(NSInteger, SomeEnum)
{
    SomeEnumA,
    SomeEnumB,
    SomeEnumC
};

@interface SomeClass : NSObject

...

@end

Kode Swift baru saya:

enum SomeEnum: NSInteger
{
    case A
    case B
    case C
};

class SomeClass: NSObject
{
    ...
}

Pembaruan: Dari jawaban. Itu tidak dapat dilakukan dalam versi Swift yang lebih lama dari 1.2. Namun menurut Swift Blog resmi ini . Di Swift 1.2 yang dirilis bersama dengan XCode 6.3, Anda dapat menggunakan Swift Enum di Objective-C dengan menambahkan @objcdi depanenum


Sebenarnya tidak perlu mengubah kode yang ada. Untuk interaksi antara Swift dan Objective-C, tonton video WWDC.
gnasher729

Saya hanya ingin memeriksa apakah proyek saya masih berfungsi apakah akan ada kelas cepat di proyek saya di masa depan, tetapi saya tidak tahu kelas apa yang harus saya tambahkan untuk mengujinya. Jadi, saya mengonversi yang lama sebagai gantinya. Bagaimanapun, terima kasih atas bantuan Anda.
myLifeasdog

Jawaban:


226

Pada Swift versi 1.2 (Xcode 6.3) Anda bisa. Cukup awali deklarasi enum dengan@objc

@objc enum Bear: Int {
    case Black, Grizzly, Polar
}

Tanpa malu-malu diambil dari Blog Swift

Catatan: Ini tidak akan berfungsi untuk String enums atau enums dengan nilai terkait. Enum Anda harus Int-terikat


Dalam Objective-C ini akan terlihat seperti

Bear type = BearBlack;
switch (type) {
    case BearBlack:
    case BearGrizzly:
    case BearPolar:
       [self runLikeHell];
}

8
terima kasih banyak untuk menunjukkannya ... catat bahwa dalam objektif-c nilai enum akan dipanggil BearBlack, BearGrizzlydan BearPolar!
nburk

1
Masuk akal bukan? Terutama ketika Anda melihat bagaimana itu diterjemahkan dari obj-c ke cepat .. @nburk
Daniel Galasko

1
Ya, ini berhasil. Namun, setidaknya dalam kasus saya atribut "publik" harus ditambahkan ke enumerasi agar dapat diakses di sisi Objective-C proyek, seperti ini: "@objc public enum Bear: Int"
Pirkka Esko

Sayang sekali saya tidak melihat bukti bahwa nilai Swift enum terkait mungkin. angan-angan
finneycanhelp

2
@ AJit mengapa Anda ingin melakukan itu? Cukup tambahkan enum ke tajuknya sendiri dan impor di tajuk penghubung jika tidak eksklusif untuk Swift
Daniel Galasko

31

Untuk memperluas jawaban yang dipilih ...

Dimungkinkan untuk berbagi enum gaya Swift antara Swift dan Objective-C menggunakan NS_ENUM().

Mereka hanya perlu didefinisikan dalam konteks Objective-C menggunakan NS_ENUM()dan mereka tersedia menggunakan notasi Swift dot.

Dari Swift Menggunakan dengan Kakao dan Objective-C

Swift mengimpor sebagai enumerasi Swift enumerasi gaya-C yang ditandai dengan NS_ENUMmakro. Ini berarti bahwa awalan untuk nama nilai penghitungan terpotong ketika mereka diimpor ke Swift, apakah mereka didefinisikan dalam kerangka kerja sistem atau dalam kode kustom.

Objektif-C

typedef NS_ENUM(NSInteger, UITableViewCellStyle) {
   UITableViewCellStyleDefault,
   UITableViewCellStyleValue1,
   UITableViewCellStyleValue2,
   UITableViewCellStyleSubtitle
};

Cepat

let cellStyle: UITableViewCellStyle = .Default

Saya mendapatkan di "definisi fungsi tidak diperbolehkan di sini" UITableViewCellStyle, apa yang saya lakukan salah? Tentu saja saya punya nama yang berbeda bukan UITableViewCellStyle.
Cristi Băluță

1
Seperti dicatat dalam jawaban Mr. Galasko di bawah ini, Swift 1.2 memungkinkan enum didefinisikan dalam Swift dan tersedia di Obj-c. Gaya definisi ini, yaitu NS_ENUM, masih berfungsi di Obj-c, tetapi pada Swift versi 1.2 Anda dapat menggunakan salah satu opsi.
SirNod

Saya menemukan ada masalah dengan ObjC enums di Swift: Mereka tidak tersedia. Dalam fragmen seperti di if let a = MyEnum(rawValue: 12345)mana 12345 bukan bagian dari enum itu, hasilnya bukan opsional tetapi beberapa enum tidak valid.
bio

30

Dari Panduan Menggunakan Swift dengan Kakao dan Objective-C :

Kelas atau protokol Swift harus ditandai dengan atribut @objc agar dapat diakses dan digunakan di Objective-C. [...]

Anda akan memiliki akses ke apa pun dalam kelas atau protokol yang ditandai dengan atribut @objc selama itu kompatibel dengan Objective-C. Ini tidak termasuk fitur Swift-only seperti yang terdaftar di sini:

Tupics Generik / Pencacahan didefinisikan dalam Swift / Struktur yang didefinisikan dalam fungsi Swift / Level-atas yang didefinisikan dalam Swift / Variabel global yang didefinisikan dalam Swift / Typealiases didefinisikan dalam Swift / Swift-style variadics / Nested types / Fungsi Curried

Jadi, tidak, Anda tidak bisa menggunakan Swift enum di kelas Objective-C.


2
Apakah ada solusinya? Maksud saya jika saya membuat kelas Swift dan saya benar-benar membutuhkan enum. Bagaimana saya bisa membuat enum dapat digunakan ke dalam Objective-C juga?
Raul Lopez

4
@RaulLopezVillalpando Jika Anda tahu Anda akan beroperasi dengan Objective-C, maka Anda harus mendeklarasikan enumerasi di Objective-C dan membiarkan kedua bahasa membagikannya.
Gregory Higley

3
"Ya, jadi kami membuat jembatan ini untuk membantu Anda bertransisi ke Swift, tetapi tidak ada gunanya jika Anda ingin menggunakan sesuatu yang keren, seperti Enums, Structs, Generics ... Jadi itu ..."
Kevin R

22
JAWABAN INI TIDAK BERLAKU BANYAK !! sejak Xcode 6.3 / Swift 1.2, Swift enum juga dapat digunakan dalam objektif-c menggunakan @objcseperti yang ditunjukkan @DanielGalasko dalam jawabannya di bawah ini !!!
nburk

9
Hanya untuk memperjelas komentar di atas, mengutip teks saat ini pada dokumentasi pada Swift 2.1 , "Enumerasi didefinisikan dalam Swift tanpa tipe nilai mentah Int ". Jadi, jika enum Anda di Swift dideklarasikan dengan tipe nilai mentah Int seperti di @obj enum MyEnum: Intdalamnya akan berfungsi dengan baik pada file Objective-C seperti yang disebutkan sebelumnya. Jika enum Anda dideklarasikan dengan tipe nilai mentah lain seperti @obj enum MyOtherEnum: String, Anda tidak akan dapat menggunakannya pada file Objective-C
jjramos

7

Swift 4.1, Xcode 9.4.1:

1) Swift enum harus diawali dengan @objcdan Intketik:

// in .swift file:
@objc enum CalendarPermission: Int {
    case authorized
    case denied
    case restricted
    case undetermined
}

2) Nama Objective-C adalah nama enum + nama kasus, misalnya CalendarPermissionAuthorized:

// in .m file:
// point to something that returns the enum type (`CalendarPermission` here)
CalendarPermission calPermission = ...;

// use the enum values with their adjusted names
switch (calPermission) {
    case CalendarPermissionAuthorized:
    {
        // code here
        break;
    }
    case CalendarPermissionDenied:
    case CalendarPermissionRestricted:
    {
        // code here
        break;
    }
    case CalendarPermissionUndetermined:
    {
        // code here
        break;
    }
}

Dan, tentu saja, ingatlah untuk mengimpor header bridging Swift Anda sebagai item terakhir dalam daftar impor file Objective-C:

#import "MyAppViewController.h"
#import "MyApp-Swift.h"

mengapa MyApp-Swift menjadi yang terakhir?
Paul T.

@ PaulT. : mungkin ada hubungannya dengan urutan pemrosesan. Coba letakkan di tempat lain, dan Anda akan melihatnya tidak berfungsi.
leanne

Saya memeriksa, dalam proyek saya saat ini hampir di semua file itu di akhir bagian impor, tetapi dalam beberapa file itu tidak di akhir dan proyek berfungsi. mungkin dalam Xcode baru berfungsi? Saya tidak dapat memeriksanya sekarang, karena proyek saya saat ini membutuhkan waktu lama untuk dikompilasi :), tetapi saya akan memeriksanya nanti
Paul T.

2

Jika Anda lebih suka mempertahankan kode ObjC apa adanya, Anda bisa menambahkan file header pembantu di proyek Anda:

Swift2Objc_Helper.h

dalam file header tambahkan jenis enum ini:

typedef NS_ENUM(NSInteger, SomeEnum4ObjC)
{
   SomeEnumA,
   SomeEnumB
};

Mungkin ada tempat lain di file .m Anda untuk membuat perubahan: untuk memasukkan file header tersembunyi:

#import "[YourProjectName]-Swift.h"

ganti [NamaProyek] dengan nama proyek Anda. File header ini memperlihatkan semua kelas @objc yang ditentukan Swift, sebelum ke ObjC.

Anda mungkin mendapatkan pesan peringatan tentang konversi implisit dari jenis enumerasi ... Tidak masalah.

Ngomong-ngomong, Anda bisa menggunakan file pembantu header ini untuk menyimpan beberapa kode ObjC seperti konstanta #define.


0

Jika Anda (seperti saya) benar-benar ingin menggunakan String enums, Anda dapat membuat antarmuka khusus untuk tujuan-c. Sebagai contoh:

enum Icon: String {
    case HelpIcon
    case StarIcon
    ...
}

// Make use of string enum when available:
public func addIcon(icon: Icon) {
    ...
}

// Fall back on strings when string enum not available (objective-c):
public func addIcon(iconName:String) {
    addIcon(Icon(rawValue: iconName))
}

Tentu saja, ini tidak akan memberi Anda kenyamanan pelengkapan otomatis (kecuali jika Anda menetapkan konstanta tambahan di lingkungan objektif-c).


0

ini mungkin sedikit membantu

Pernyataan masalah : - Saya memiliki enum di kelas cepat, yang saya akses dari kelas cepat lainnya, dan Sekarang saya perlu mengaksesnya dari salah satu kelas C objektif saya.

Sebelum mengaksesnya dari kelas objektif-c: -

enum NTCType   {
    case RETRYNOW
    case RETRYAFTER
}
 var viewType: NTCType? 

Perubahan untuk mengaksesnya dari kelas objektif c

@objc  enum NTCType :Int  {
    case RETRYNOW
    case RETRYAFTER
}

dan menambahkan fungsi untuk meneruskannya pada nilai

  @objc  func setNtc(view:NTCType)  {
        self.viewType = view; // assign value to the variable
    }

0

Setelah meneliti ini, saya terus menemukan hanya sebagian jawaban, jadi saya membuat seluruh contoh aplikasi Swift yang dijembatani ke Objective C yang memiliki Swift enum yang digunakan oleh kode Objective C dan Objective C enum yang digunakan oleh kode Swift. Ini adalah proyek Xcode sederhana yang dapat Anda jalankan dan coba. Itu ditulis menggunakan Xcode 10.3 dengan Swift 5.0

Contoh Proyek


Saya tidak melihat, di mana proyek Anda menggunakan swift enum di Objective C. Juga definisi swift enum enum SwAnimaltidak memiliki yang terdepan@obj
oliolioli

0

Jika Anda mencoba mengamati enum yang terlihat seperti ini:

enum EnumName: String {
    case one = "One"
    case two = "Two"
}

solusi ini membantu saya.

Kelas yang Dapat Diobservasi:

  • membuat @objc dynamic var observable: String?
  • buat instance enum Anda seperti ini:

    private var _enumName: EnumName? {
        didSet {
            observable = _enumName!.rawValue
        }
    }

Kelas Pengamat:

  • membuat private var _enumName: EnumName?
  • membuat private let _instance = ObservableClass()
  • membuat

    private var _enumObserver: NSKeyValueObservation = _instance.observe(\.observable, options: .new, changeHandler: { [weak self] (_, value) in
        guard let newValue = value.newValue else { return }
        self?._enumName = EnumName(rawValue: period)!
    })

Dari pada itu. Sekarang setiap kali Anda mengubah _enumNamedi kelas yang dapat diamati, contoh yang sesuai pada kelas pengamat akan segera diperbarui juga.

Ini tentu saja merupakan implementasi yang terlalu disederhanakan, tetapi harus memberi Anda gambaran tentang bagaimana mengamati properti yang tidak kompatibel dengan KVO.

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.