Search code examples
swiftobjective-cstructbridging-header

Error using Objective-C structure in Swift (Cannot find type 'XXX' in scope)


In my sample project, I tried using the Objective-C classes and struct in the Swift file using the bridging headers. I get an error using the struct:

Cannot find type 'XXX' in scope

However, classes are used without any error.

My Objective-C file looks like:

#import <Cocoa/Cocoa.h>

struct ObjCStruct {
    NSMenu* sMenu;
    int8_t menuID;
};

@interface ObjCClass : NSObject {
    NSMenu* cMenu;
}

@end

In my bridging header, I have used it as:

#import "ObjC.h"

Finally, I used struct and classes in Swift file as:

struct Model {
    var c : ObjCClass;
    var s : ObjCStruct;
}

If NSMenu* sMenu; has been commented out from ObjC.h, then it works fine.

How can I use the Objective-C struct in the Swift file?

I have imported the Objective-C headers in the bridging header and the bridging header has been referred correctly in the build settings.


Solution

  • Using struct with objects is very tricky for memory management. Struct in objective-c is not the same as struct in Swift. You may reconsider declaring it a class. However, I think this is a workaround:

    struct ObjCStruct {
        __unsafe_unretained  NSMenu* sMenu; //It's __strong by default
        int8_t menuID;
    };
    

    In Swift:

    //Manage NSMenu manually by Unmanaged. Keep in mind to release this menu 
    //object later or you will get a leak here.
    
    let menu: Unmanaged<NSMenu> = Unmanaged.passRetained(NSMenu(title: "2"))
    let model = Model(c: .init(), s: .init(sMenu: menu, menuID: 2))
    
    //To get the NSMenu
    let menuUI = menu.takeRetainedValue()