简体   繁体   中英

Objective-C method not visible in Swift when using Swift Enum

I have a method that uses a forward declaration of a Swift enum. Whenever I do this my method isn't visible in other Swift classes. Yet if I do a forward declaration for a class it is visible in Swift. Why is it not visible for an enum and how can I get around this?

// Objective-C Header file 

@class ViewController;
typedef NS_ENUM(NSInteger, MyEnumType);

@interface ObjcViewController : UIViewController
- (void)doThis: (enum MyEnumType)type;
- (void)grabTheClass: (ViewController *)mySwiftClass;
- (void)doSomethingElse;
@end


//Swift File 

@objc enum MyEnumType: Int {
    case one = 1
    case two = 2
}

@objc class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        let controller = ObjcViewController()
        controller.doSomethingElse()
        controller.grabTheClass(self)
        controller.doThis(EnumType) //ERROR: This will not compile
    }
}



代码在这里

The forward declaration of the enum creates an incomplete type. And an incomplete type has very little usefulness. You can form a pointer to it, or you can call a function with a pointer to it, but that's it.

Unless you complete the enum declaration with the concrete definition, you won't be able to properly consume it, neither in Objective-C, nor Swift.

And this is why the Swift code can't see the method, because at the time the Swift compiler processes the bridging header (and this happens before any Swift code is processed), the enum is not yet materialised, thus is excluded from the bridged interface due to being an incomplete type.

If you add a method that takes a pointer to the enum:

- (void)doThisWithPointer:(enum MyEnumType *)type;

then the method will be accessible from Swift, though it will be imported as

func doThis(withPointer type: OpaquePointer)

which doesn't make it much more helpful either.

But if forward declarations are incomplete types, why does the @class works? Its because in Objective-C objects are passed as pointers, and pointers to incomplete types are usable at call sites (as we just saw). Thus, the method is available to Swift.

More, the @class statement is part of the Objective-C additions to the C language, which means the compiler can give them special treatment, like importing the method with the expected signature, instead of the OpaquePointer one. This thanks to the dynamic nature of the OOP additions over the C language.

It looks like doThis is a function, but you are missing the parentheses in the call. The line controller.doThis should instead read controller.doThis()

See if that helps.

Somebody else claimed in another post that the Swift enum needed to be declared as public in order to be visible in Objective-C. I haven't verified that however.

Edit:

Okay, after some experimentation and googling, I think you have to declare your enum in Objective-C using the NSEnum macro, and that makes it available in both languages.

I don't think Objective-C can "see" Swift Enums when they're defined in Swift.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM