解决涉及枚举的 Swift.h 和 Bridging-Header.h 循环引用

Resolving Swift.h and Bridging-Header.h circular references involving enums

我有一个 Objective-C header 必须由 Swift class 使用。但是,此 header 必须将 Swift.h 文件用于 Swift 文件中声明的枚举。也就是说,设置如下:

MPViewController.h

#import "MyProject-Swift.h"

@interface MPViewController: UIViewController

@property (nonatomic, assign) MPSomeEnum theEnum;
...

@end

MyProject-Bridging-Header.h

...    
#import "MPViewController.h"
...

SomeEnum.swift

@objc enum MPSomeEnum: Int {
    ...
}

编译代码时,出现三个错误:

  • 'MyProject-Swift.h' file not found
  • Failed to emit precompiled header [Xcode DerivedData folder]/[...]/MyProject-Bridging-Header-swift_[...].pch for bridging header [Project folder]/MyProject-Bridging-Header.h
  • Unknown type name 'MPSomeEnum'

我假设这源于 MyProject-Swift.h 和桥接 header MyProject-Bridging-Header.h 之间的循环引用是否正确?从 similar question 来看,一种解决方案是使用前向声明。但是,转发声明枚举似乎是不可能的,所以也许唯一的方法是将枚举定义完全移动到 Objective-C 文件中?

TL&DR; 如您所料,您需要将枚举声明移至 Objective-C,或将 class 移至 Swift .

枚举的前向声明在 Objective-C 中是可能的:

@property SomeEnum someProperty;

- (void)doSomethingWithEnum:(enum SomeEnum)enumValue;

然而,正确的 Cocoa 枚举是 NSInteger 的类型定义:typedef NS_ENUM(NSInteger, MyEnum),并且 enum 关键字没有包含足够的信息 space在使用它时分配,所以当你想使用这样的声明时,你会遇到各种编译器错误。因此,在 Swift 中声明的枚举在 Objective-C 中不可向前声明。

现在,如果您真的想保留 Swift 中的枚举定义,您可以使用变通方法,将其声明为 Objective-C 中的 NSInteger,同时提供专门的 属性 在 Swift:

// NS_REFINED_FOR_SWIFT imports this in Swift as __theEnum
@property(nonatomic, assign) NSInteger theEnum NS_REFINED_FOR_SWIFT;

extension MPViewController {
    // we provide a wrapper around the Objective-C property
    var theEnum: MPSomeEnum {
        // this uses a forced unwrap, beware :)
        return MPSomeEnum(rawValue: theEnum)!
    }
}