iseletsky
iseletsky

Reputation: 653

Using an Objective C enum in Swift back in Objective C

I have an enum defined in Objective C and used as a datatype in a Swift object.

Now I'm using that swift object in Objective C and I'd like to access the property.

However the property isn't added to the "xxxx-Swift.h" file in the class. I know it's possible to use Swift enums in Obj C with @objc prepending it but I don't have much control over this enum since it's auto generated from existing Objective C code.

Upvotes: 0

Views: 683

Answers (1)

Anatoli P
Anatoli P

Reputation: 4891

I'm not sure exactly what your use case is, but here is a quick example of how an enum defined in Objective-C can be used in a Swift class, which can in turn be used in Objective-C.

Here is the Objective-C header (oclib.h):

#ifndef oclib_h
#define oclib_h

#import <Foundation/Foundation.h>

typedef enum {A, B, C} oc_enum_t;

void useSwiftClassInC();

#endif /* oclib_h */

Here is the corresponding Objective-C .m file (oclib.m):

#import "oclib.h"
#import "swift_c_1-Swift.h" // Need this to have access to Swift types; the swift_c_1 part will be your product module name.

void useSwiftClassInC() {
    UseEnum *ue = [[UseEnum alloc] initWithE:B i:444];
    printf("In Objective-C useSwiftClassInC(): m_Enum = %d, m_Int = %d\n", ue.m_Enum, ue.m_Int);
    ue.m_Enum = A;
    ue.m_Int = 10;
    [UseEnum printUseEnum: ue];
}

And here is the Swift file:

// Swift class that uses an enum from Objective-C    
class UseEnum : NSObject // NSObject inheritance is important!
    {
        var m_Enum : oc_enum_t
        var m_Int : Int32

        init(e : oc_enum_t, i : Int32)
        {
            m_Enum = e
            m_Int = i
        }

        static func printUseEnum( x : UseEnum )
        {
            print("In Swift UseEnum::printUserEnum: m_Enum = \(x.m_Enum), m_Int = \(x.m_Int)")
        }
    }

    // This calls an Objective-C function that does the following:
    // - creates a UseEnum object
    // - prints it out from Objective-C
    // - modifies it
    // - calls printUseEnum(), implemented in Swift, to print the object
    useSwiftClassInC()

The bridging header just has

#import "oclib.h"

You have probably seen this documentation already, but if not, here it is: https://developer.apple.com/library/ios/documentation/Swift/Conceptual/BuildingCocoaApps/MixandMatch.html

Please provide more details about your specific situation if this doesn't answer your question. Here is the output I get from the example:

In Objective-C useSwiftClassInC(): m_Enum = 1, m_Int = 444
In Swift UseEnum::printUserEnum: m_Enum = oc_enum_t(rawValue: 0), m_Int = 10

An interesting situation arises if a data type defined in Swift is used in the signature of an Objective-C function that needs to be called from Swift. Xcode won't let us import the *-Swift.h into an Objective-C header or into a bridging header. A solution is to use @class forward declaration of the Swift type. Thus, if in the above example we needed an Objective-C function that takes UseEnum as a parameter, we could have something like this in oclib.h:

...
@class UseEnum; // Forward declaration must come before UseEnum is used!
...
void useSwiftClassInC_1(UseEnum * useEnum);
...

Upvotes: 1

Related Questions