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

我想把我的一些 Obj-C 类转换成 Swift。而其他一些 Obj-C 类仍然在转换后的类中使用枚举。我在预发行文档中搜索了一下,但是没有找到,或者可能是我错过了。有没有办法在 Obj-C 类中使用 Swift 枚举?或者这个问题的文档链接?

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

我的老代码:

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


@interface SomeClass : NSObject


...


@end

我的新代码:

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 中通过在 enum前面添加 @objc来使用 Swift Enum

93390 次浏览

来自 与 Cocoa 和 Objective-C 一起使用 Swift指南:

Swift 类或协议必须用@objecc 属性标记为 在目标 C 中可访问和使用

您可以访问类或协议中的任何内容 标记为@obc 属性,只要它与 Objective-C。这不包括仅仅是 Swift 的特性,比如列出的那些 这里:

中定义的泛型元组/在 Swift 中定义的枚举/结构 中定义的 Swift/Global 变量中定义的 Swift/顶级函数 在 Swift/Swift 风格变量/嵌套类型/中定义的 Swift/类型别 咖喱函数

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

为了详细说明选定的答案..。

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

它们只需要使用 NS_ENUM()在 Objective-C 上下文中定义,并且可以使用 Swift 点符号来使用它们。

来自 与 Cocoa 和 Objective-C 一起使用 Swift

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

目标 C

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

斯威夫特

let cellStyle: UITableViewCellStyle = .Default

从 Swift 版本1.2(Xcode 6.3)开始,您就可以了

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

Swift Blog 斯威夫特博客上厚颜无耻地拿走

注意: 这不适用于 String 枚举或具有相关值的枚举。您的枚举将需要是 Int 绑定的


在 Objective-C 中,这看起来像

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

如果您希望保持 OBC 代码的原样,您可以在项目中添加一个 helper 头文件:

Swift2Objc_Helper.h

在头文件中添加这个枚举类型:

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

您的.m 文件中可能还有其他地方需要更改: 包含隐藏的头文件:

#import "[YourProjectName]-Swift.h"

将[ YourProjectName ]替换为您的项目名称。

您可能会收到一条关于枚举类型隐式转换的警告消息... ... 没问题。

顺便说一下,您可以使用这个头助手文件来保存一些对象代码,比如 # Definition 常量。

如果您(像我一样)真的想要使用 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 环境中定义了额外的常量)。

Swift 4.1,Xcode 9.4.1:

1)迅速枚举必须以 @objc为前缀,并且是 Int类型:

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

2) Objective-C 名是 enum name + case name,例如 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"

这个可能会更有帮助

问题陈述 :-我在 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
}

在研究了这个问题之后,我一直只找到部分答案,所以我创建了一个完整的 Swift App 示例,它桥接到 Objective C,在 Objective C 代码中使用 Swift 枚举,在 Objective C 代码中使用 Swift 枚举。它是一个简单的 Xcode 项目,您可以运行它并进行试验。它是用 Xcode 10.3和 Swift 5.0编写的

示例计划

如果你试图观察一个枚举,它看起来像这样:

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

这个变通方法帮助了我。

可观察类别:

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

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

Observer Class:

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

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

Than's it. Now each time you change the _enumName in the observable class, an appropriate instance on the observer class will be immediately updated as well.

This is of course an oversimplified implementation, but it should give you an idea of how to observe KVO-incompatible properties.