Swift Enum'u Obj-C'de kullanmak mümkün mü?


145

Obj-C sınıfımın bazılarını Swift'e dönüştürmeye çalışıyorum. Ve diğer bazı Obj-C sınıfları bu dönüştürülmüş sınıfta hala enum kullanıyor. Sürüm Öncesi Dokümanlarda arama yaptım ve bulamadım ya da özledim. Obj-C Sınıfında Swift enum kullanmanın bir yolu var mı? Veya bu sorunun dokümanı için bir bağlantı mı?

Eski Obj-C kodumda ve yeni Swift kodumda numaralandırmamı böyle ilan ettim.

eski Obj-C Kodum:

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

@interface SomeClass : NSObject

...

@end

yeni Swift Kodum:

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

class SomeClass: NSObject
{
    ...
}

Güncelleme: Cevaplardan. Swift 1.2'den daha eski bir sürümde yapılamaz. Ancak bu resmi Swift Blog'a göre . XCode 6.3 ile birlikte yayınlanan Swift 1.2'de, Objective-C'de Swift Enum'u aşağıdakilerin @objcönüne ekleyerek kullanabilirsiniz :enum


Mevcut kodunuzu değiştirmenize gerek yoktur. Swift ve Objective-C arasındaki etkileşim için WWDC videolarını izleyin.
gnasher729

Gelecekte projemde hızlı bir sınıf olup olmayacağını projemin hala çalışıp çalışmadığını kontrol etmek istiyorum, ancak test etmek için hangi sınıfı eklemem gerektiğini anlayamıyorum. Bunun yerine eskisini dönüştürüyorum. Neyse, yardımlarınız için teşekkürler.
myLifeasdog

Yanıtlar:


226

Swift 1.2 sürümünden (Xcode 6.3) itibaren yapabilirsiniz. Numaralandırma bildiriminin önüne@objc

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

Utanmazca Swift Blog'dan alınmıştır

Not: Bu, String enumları veya ilişkili değerlere sahip enumlar için çalışmaz. Numaralandırmanızın Int bağlı olması gerekir


Objective-C'de bu

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

8
bunu işaret ... amaç-c enum değerler çağrı olur gerçi O notu için teşekkürler çok BearBlack, BearGrizzlyve BearPolar!
nburk

1
Bu mantıklı değil mi? Özellikle obj-c'den hızlıya nasıl çevrildiğine baktığınızda .. @nburk
Daniel Galasko

1
Evet, işe yarıyor. Ancak, en azından benim durumumda, projenin Objective-C tarafında erişilebilir olması için numaralandırmaya "genel" bir öznitelik eklenmelidir: "@objc public enum Bear: Int"
Pirkka Esko

Çok kötü Swift enum ilişkili değerleri mümkün olduğuna dair hiçbir kanıt görmüyorum. arzulu düşünme
finneycanhelp

2
@AJit bunu neden yapmak istiyorsun?
Numaralandırmayı

31

Seçilen cevabı genişletmek için ...

Swift tarzı numaralandırmalarını Swift ve Objective-C kullanarak paylaşmak mümkündür NS_ENUM().

Sadece Objective-C bağlamında tanımlanması gerekir NS_ENUM()ve Swift nokta gösterimi kullanılarak kullanılabilir hale getirilir.

Gönderen Kakao ile kullanma Swift ve Objective-C

Swift, NS_ENUMmakro ile işaretlenmiş herhangi bir C stili numaralandırmayı Swift numaralandırması olarak içe aktarır . Bu, numaralandırma değer adlarına ilişkin öneklerin, sistem çerçevelerinde veya özel kodda tanımlanmış olsunlar Swift'e aktarıldıklarında kesildiği anlamına gelir.

Objective-C

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

hızlı

let cellStyle: UITableViewCellStyle = .Default

UITableViewCellStyle "fonksiyon tanımı burada izin verilmez" olsun, ne yanlış yapıyorum? Tabii ki UITableViewCellStyle değil farklı isimler var.
Cristi Băluță

1
Bay Galasko'nun aşağıdaki cevabında belirtildiği gibi Swift 1.2, enumların Swift'te tanımlanmasına ve Obj-c'de mevcut olmasına izin verir. Bu tanım tarzı, yani NS_ENUM, hala Obj-c'de çalışır, ancak Swift sürüm 1.2'den herhangi bir seçeneği kullanabilirsiniz.
SirNod

Swift'te ObjC numaralarıyla ilgili bir sorun olduğunu fark ettim: Failable değiller. if let a = MyEnum(rawValue: 12345)12345'in bu numaralandırmanın bir parçası olmadığı gibi bir parçada , sonuç isteğe bağlı değil, bazı geçersiz numaralandırmadır.
bio

30

Gönderen Kakao ve Objective-C ile kullanma Swift rehberi:

Bir Swift sınıfı veya protokolünün Objective-C'de erişilebilir ve kullanılabilir olması için @objc özelliğiyle işaretlenmesi gerekir. [...]

Objective-C ile uyumlu olduğu sürece, bir sınıf veya protokol içindeki @objc özniteliğiyle işaretlenmiş herhangi bir şeye erişebilirsiniz. Burada listelenenler gibi yalnızca Swift özellikleri hariçtir:

Swift'te tanımlanan Jenerik Tuples / Numaralandırma / Swift'te tanımlanan Yapılar / Swift'te tanımlanan Üst düzey işlevler / Swift / Swift stili değişkenlerinde / İç içe tiplerde / Curried işlevlerinde tanımlanan Swift / Typealiases'de tanımlanan Genel değişkenler

Yani hayır, Objective-C sınıfında Swift numaralandırma kullanamazsınız.


2
Bir çözüm var mı? Yani bir Swift sınıfı yaratırsam ve kesinlikle bir numaralandırmaya ihtiyacım varsa. Bu numaralandırmayı Objective-C'de de kullanılabilir hale nasıl getirebilirim?
Raul Lopez

4
@RaulLopezVillalpando Eğer Objective-C ile birlikte çalışacağınızı biliyorsanız, Objective-C'deki numaralandırmayı bildirmeli ve her iki dili de paylaşsın.
Gregory Higley

3
"Evet, bu köprüyü Swift'e geçmene yardımcı olmak için yaptık, ancak Numaralandırmalar, Yapılar, Jenerikler gibi havalı bir şey kullanmak istiyorsan işe yaramaz ... İşte orada ..."
Kevin R

22
BU CEVAP ARTIK YAYINDA DEĞİL !! Xcode 6.3 / Swift 1.2'den bu yana, Swift @objcenum'ları aşağıdaki cevapta @DanielGalasko'nun işaret ettiği gibi obj -c içinde de kullanılabilir !
nburk

9
Yukarıdaki yorumu açıklığa kavuşturmak için Swift 2.1 , " Int ham değer türü olmadan Swift'de tanımlanmış numaralandırmalar" olarak dokümantasyondaki mevcut metni alıntılamak . Bu nedenle, Swift'teki numaralandırmanız, @obj enum MyEnum: Intdaha önce belirtildiği gibi Objective-C dosyalarında iyi çalışacak şekilde bir Int ham değer türüyle bildirilirse . @obj enum MyOtherEnum: String
Numaralandırmanız

7

Swift 4.1, Xcode 9.4.1:

1) Swift numaraya ön ek eklenmeli @objcve şu Inttür olmalıdır:

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

2) Objective-C adı enum name + vaka adıdır, örneğin 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;
    }
}

Ve elbette, Swift köprüleme başlığınızı Objective-C dosyasının içe aktarma listesindeki son öğe olarak almayı unutmayın:

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

MyApp-Swift neden sonuncu olmalı?
Paul T.

@PaulT. : büyük olasılıkla işleme sırası ile ilgilidir. Başka bir yere koymayı deneyin, işe yaramayacağını göreceksiniz.
leanne

Mevcut projemde neredeyse tüm dosyalarda içe aktarma bölümünün sonunda olduğunu kontrol ettim, ancak birkaç dosyada sonunda değil ve proje çalışıyor. çalışır yeni bir Xcode olabilir? Şimdi kontrol edemiyorum, çünkü şu anki projem derlenmesi çok uzun sürüyor :), ama daha sonra kontrol edeceğim
Paul T.

2

ObjC kodlarını oldukları gibi tutmayı tercih ederseniz, projenize bir yardımcı başlık dosyası ekleyebilirsiniz:

Swift2Objc_Helper.h

başlık dosyasına bu numaralandırma türünü ekleyin:

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

.M dosyanızda değişiklik yapmak için başka bir yer olabilir: gizli başlık dosyasını eklemek için:

#import "[YourProjectName]-Swift.h"

[ProjeAdınız] yerine proje adınızı yazın. Bu başlık dosyası tüm Swift tarafından tanımlanmış @objc sınıflarını, numaralandırmaları ObjC'ye gösterir.

Numaralandırma türünden örtük dönüştürme hakkında bir uyarı iletisi alabilirsiniz ... Sorun değil.

Bu arada, #define sabitleri gibi bazı ObjC kodlarını saklamak için bu başlık yardımcı dosyasını kullanabilirsiniz.


0

(Benim gibi) gerçekten String enum'larını kullanmak istiyorsanız, obj-c için özel bir arayüz yapabilirsiniz. Örneğin:

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))
}

Tabii ki, bu size otomatik tamamlama kolaylığı sağlamaz (objektif-c ortamında ek sabitler tanımlamazsanız).


0

bu biraz daha yardımcı olabilir

Sorun bildirimi : - Diğer hızlı sınıflardan eriştiğim hızlı sınıfta numaralandırma var ve Şimdi objektif C sınıfımdan birine erişmem gerekiyor.

Obj-c sınıfından erişmeden önce: -

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

Hedef c sınıfından erişime yönelik değişiklikler

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

ve değere iletmek için bir işlev ekleyin

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

0

Bunu araştırdıktan sonra, sadece kısmi cevaplar bulmaya devam ettim, bu yüzden Swift C'nin ve Objektif C kodunun kullandığı Objective C numaralarının kullandığı Swift C'nin bulunduğu Objective C'ye köprülenmiş bir Swift Uygulaması örneği oluşturdum. Çalıştırabileceğiniz ve deneyebileceğiniz basit bir Xcode projesidir. Swift 5.0 ile Xcode 10.3 kullanılarak yazılmıştır

Örnek Proje


Projeniz Ayrıca Amaç C. hızlı enum tanımı içinde hızlı enum kullanır nerede, göremiyorum enum SwAnimallider yoksun@obj
oliolioli

0

Aşağıdaki gibi bir enum gözlemlemeye çalışıyorsanız:

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

bu geçici çözüm bana yardımcı oldu.

Gözlenebilir Sınıf:

  • oluşturmak @objc dynamic var observable: String?
  • numaralandırma örneğinizi şu şekilde oluşturun:

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

Gözlemci Sınıfı:

  • oluşturmak private var _enumName: EnumName?
  • oluşturmak private let _instance = ObservableClass()
  • oluşturmak

    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)!
    })

Bundan daha. Şimdi _enumName, gözlemlenebilir sınıftaki her değiştirdiğinizde, gözlemci sınıfındaki uygun bir örnek de hemen güncelleştirilir.

Bu elbette aşırı derecede basitleştirilmiş bir uygulamadır, ancak size KVO ile uyumsuz özelliklerin nasıl gözlemleneceği hakkında bir fikir vermelidir.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.