可以在Obj-C中使用Swift的Enum吗?

时间:2014-06-10 11:00:13

标签: objective-c enums swift

我试图将我的一些Obj-C类转换为Swift。还有一些其他的Obj-C类仍在转换类中使用枚举。我在Pre-Release Docs中搜索过但无法找到它或者我错过了它。有没有办法在Obj-C类中使用Swift枚举?或者链接到这个问题的文档?

这就是我在旧的Obj-C代码和新的Swift代码中声明我的枚举的方式。

我的旧Obj-C代码:

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

@interface SomeClass : NSObject

...

@end

我的新Swift代码:

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

class SomeClass: NSObject
{
    ...
}

更新:来自答案。它不能在Swift旧版本1.2以上完成。但根据这位官员Swift Blog。在与XCode 6.3一起发布的Swift 1.2中,您可以在Objective-C中使用Swift Enum,在@objc前面添加enum

9 个答案:

答案 0 :(得分:194)

从Swift 1.2版(Xcode 6.3)开始,你可以。只需在枚举声明前添加@objc

前缀即可
@objc enum Bear: Int {
    case Black, Grizzly, Polar
}

Swift Blog

无耻地取走

在Objective-C中,这看起来像

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

答案 1 :(得分:31)

来自Using Swift with Cocoa and Objective-C指南:

  

必须使用@objc属性标记Swift类或协议   可在Objective-C中访问和使用。 [...]

     

您可以访问类或协议中的任何内容   标有@objc属性,只要它兼容   Objective-C的。这不包括仅限Swift的功能,例如列出的功能   这里:

     

泛型元组/ 在Swift中定义的枚举 /中定义的结构   在Swift / Global变量中定义的Swift / Top-level函数   在Swift / Swift风格的可变参数/嵌套类型中定义的Swift / Typealiases /   咖喱功能

所以,不,你不能在Objective-C类中使用Swift枚举。

答案 2 :(得分:29)

扩展所选答案......

可以使用NS_ENUM()在Swift和Objective-C之间共享Swift样式枚举。

它们只需要使用NS_ENUM()在Objective-C上下文中定义,并使用Swift点表示法提供它们。

来自 Using Swift with Cocoa and Objective-C

  

Swift导入作为Swift枚举的任何标有NS_ENUM宏的C样式枚举。这意味着枚举值名称的前缀在导入Swift时会被截断,无论它们是在系统框架中定义还是在自定义代码中定义。

目标-C

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

夫特

let cellStyle: UITableViewCellStyle = .Default

答案 3 :(得分:2)

如果您希望将ObjC代码保留为原样,则可以在项目中添加帮助程序头文件:

Swift2Objc_Helper.h
头文件中的

添加此枚举类型:

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

.m文件中可能还有其他地方可以进行更改:包含隐藏的头文件:

#import "[YourProjectName]-Swift.h"

用您的项目名称替换[YourProjectName]。这个头文件公开了所有Swift定义的@objc类,枚举到ObjC。

您可能会收到有关从枚举类型隐式转换的警告消息......没关系。

顺便说一句,您可以使用此头文件助手文件来保留一些ObjC代码,例如#define常量。

答案 4 :(得分:0)

如果你(像我一样)真的想要使用String枚举,你可以为objective-c创建一个专门的接口。例如:

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

当然,这不会为您提供自动完成的便利(除非您在objective-c环境中定义其他常量)。

答案 5 :(得分:0)

Swift 4.1,Xcode 9.4.1:

1)Swift枚举必须以@objc为前缀并为Int类型:

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

2)Objective-C名称是枚举名称+案例名称,例如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;
    }
}

当然,请记住将Swift桥接标头作为Objective-C文件的导入列表中的最后一项导入:

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

答案 6 :(得分:0)

这可能会帮助更多

问题陈述:-我在swift类中有枚举,我正在从其他swift类访问它,现在我需要从我的目标C类之一访问它。

在从Objective-C类访问它之前:-

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

从目标c类访问它的更改

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

并添加一个函数以将其传递给值

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

答案 7 :(得分:0)

研究此问题后,我一直只找到部分答案,因此我创建了一个完整的示例,该示例连接到Objective C,其中包含Objective C代码使用的Swift枚举和Swift代码使用的Objective C枚举。这是一个可以运行和试验的简单Xcode项目。它是使用Xcode 10.3和Swift 5.0编写的

Example Project

答案 8 :(得分:0)

如果您尝试观察的枚举看起来像这样:

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

此解决方法对我有所帮助。

可观察类:

  • 创建@objc dynamic var observable: String?
  • 像这样创建您的枚举实例:

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

观察者类别:

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

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

比。现在,每次您更改可观察类中的_enumName时,观察者类上的相应实例也会立即更新。

这当然是一个简化的实现,但是它应该使您了解如何观察KVO不兼容的属性。