objective-c 是否可以在 Obj-C 中使用 Swift 的枚举?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/24139320/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-03 21:19:08  来源:igfitidea点击:

Is it possible to use Swift's Enum in Obj-C?

objective-cenumsswift

提问by myLifeasdog

I'm trying to convert some of my Obj-C class to Swift. And some other Obj-C classes still using enum in that converted class. I searched In the Pre-Release Docs and couldn't find it or maybe I missed it. Is there a way to use Swift enum in Obj-C Class? Or a link to the doc of this issue?

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

This is how I declared my enum in my old Obj-C code and new Swift code.

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

my old Obj-C Code:

我的旧 Obj-C 代码:

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

@interface SomeClass : NSObject

...

@end

my new Swift Code:

我的新 Swift 代码:

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

class SomeClass: NSObject
{
    ...
}

Update:From the answers. It can't be done in Swift older version than 1.2. But according to this official Swift Blog. In Swift 1.2 that released along with XCode 6.3, You can use Swift Enum in Objective-C by adding @objcin front of enum

更新:从答案。它不能在 Swift 1.2 旧版本中完成。但是根据这个官方Swift 博客。在与 XCode 6.3 一起发布的 Swift 1.2 中,您可以在 Objective-C 中使用 Swift Enum 通过@objc在前面添加enum

回答by Daniel Galasko

As of Swift version 1.2 (Xcode 6.3) you can. Simply prefix the enum declaration with @objc

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

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

Shamelessly taken from the Swift Blog

无耻地取自Swift 博客

Note: This would not work for String enums or enums with associated values. Your enum will need to be Int-bound

注意:这不适用于字符串枚举或具有关联值的枚举。你的枚举需要是 Int-bound



In Objective-C this would look like

在 Objective-C 中,这看起来像

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

回答by SirNod

To expand on the selected answer...

要扩展所选答案...

It is possible to share Swift style enums between Swift and Objective-C using NS_ENUM().

可以在 Swift 和 Objective-C 之间使用NS_ENUM().

They just need to be defined in an Objective-C context using NS_ENUM()and they are made available using Swift dot notation.

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

From the Using Swift with Cocoa and Objective-C

从将Swift 与 Cocoa 和 Objective-C 结合使用

Swift imports as a Swift enumeration any C-style enumeration marked with the NS_ENUMmacro. This means that the prefixes to enumeration value names are truncated when they are imported into Swift, whether they're defined in system frameworks or in custom code.

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

Objective-C

目标-C

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

Swift

迅速

let cellStyle: UITableViewCellStyle = .Default

回答by hpique

From the Using Swift with Cocoa and Objective-Cguide:

从在Cocoa 和 Objective-C 中使用 Swift指南:

A Swift class or protocol must be marked with the @objc attribute to be accessible and usable in Objective-C. [...]

You'll have access to anything within a class or protocol that's marked with the @objc attribute as long as it's compatible with Objective-C. This excludes Swift-only features such as those listed here:

Generics Tuples / Enumerations defined in Swift/ Structures defined in Swift / Top-level functions defined in Swift / Global variables defined in Swift / Typealiases defined in Swift / Swift-style variadics / Nested types / Curried functions

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

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

泛型元组 / Swift 中定义的枚举/ Swift 中定义的结构/ Swift 中定义的顶级函数 / Swift 中定义的全局变量 / Swift 中定义的类型别名 / Swift 风格的可变参数 / 嵌套类型 / Curried 函数

So, no, you can't use a Swift enum in an Objective-C class.

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

回答by leanne

Swift 4.1, Xcode 9.4.1:

斯威夫特 4.1,Xcode 9.4.1:

1) Swift enum must be prefixed with @objcand be Inttype:

1) Swift 枚举必须以前缀@objcInt类型为:

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

2) Objective-C name is enum name + case name, eg CalendarPermissionAuthorized:

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

And, of course, remember to import your Swift bridging header as the last item in the Objective-C file's import list:

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

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

回答by David.Chu.ca

If you prefer to keep ObjC codes as-they-are, you could add a helper header file in your project:

如果你更喜欢保持 ObjC 代码的原样,你可以在你的项目中添加一个辅助头文件:

Swift2Objc_Helper.h

in the header file add this enum type:

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

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

There may be another place in your .m file to make a change: to include the hidden header file:

您的 .m 文件中可能还有另一个地方可以进行更改:包含隐藏的头文件:

#import "[YourProjectName]-Swift.h"

replace [YourProjectName] with your project name. This header file expose all Swift defined @objc classes, enums to ObjC.

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

You may get a warning message about implicit conversion from enumeration type... It is OK.

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

By the way, you could use this header helper file to keep some ObjC codes such as #define constants.

顺便说一下,你可以使用这个头文件来保存一些 ObjC 代码,比如 #define 常量。

回答by Lukas Kalinski

If you (like me) really want to make use of String enums, you could make a specialized interface for objective-c. For example:

如果你(像我一样)真的想使用 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))
}

Of course, this will not give you the convenience of auto-complete (unless you define additional constants in the objective-c environment).

当然,这不会给你自动完成的便利(除非你在objective-c环境中定义了额外的常量)。

回答by Anurag Bhakuni

this might help a little more

这可能会有所帮助

Problem statement:- I have enum in swift class, which I am accessing form other swift classes, and Now I need to access it form my one of the objective C class.

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

Before accessing it from objective-c class :-

在从objective-c 类访问它之前:-

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

Changes for accessing it from objective c class

从目标 c 类访问它的更改

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

and add a function to pass it on the value

并添加一个函数来传递它的值

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

回答by user3288724

After researching this, I kept finding only partial answers, so I created an entire example of a Swift App bridged to Objective C that has Swift enums used by Objective C code and Objective C enums used by Swift code. It is a simple Xcode project that you can run and experiment with. It was written using Xcode 10.3 with Swift 5.0

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

Example Project

示例项目

回答by Gasper J.

In case you are trying to observe an enum which looks like this:

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

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

this workaround helped me.

这个解决方法帮助了我。

Observable Class:

可观察类:

  • create @objc dynamic var observable: String?
  • create your enum instance like this:

    private var _enumName: EnumName? {
        didSet {
            observable = _enumName!.rawValue
        }
    }
    
  • 创建 @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)!
    })
    
  • 创建 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)!
    })
    

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

就是这样。现在,每次更改_enumNameobservable 类中的 时,观察者类上的适当实例也将立即更新。

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

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