Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using non NS_ENUM objective-C enum in swift

Tags:

swift

I am using the wahoo fitness API and it defines the following objective-C enum:

typedef enum
{
    /** No active connection. */
    WF_SENSOR_CONNECTION_STATUS_IDLE,
    /** The connection is in process of being established. */
    WF_SENSOR_CONNECTION_STATUS_CONNECTING,
    /** The sensor connection is established and active. */
    WF_SENSOR_CONNECTION_STATUS_CONNECTED,
    /** The connection was interrupted (usually occurs when fisica is disconnected). */
    WF_SENSOR_CONNECTION_STATUS_INTERRUPTED,
    /** The connection is in process of being disconnected. */
    WF_SENSOR_CONNECTION_STATUS_DISCONNECTING,

} WFSensorConnectionStatus_t;

I can't find a way to use it in swift. I first tried to do a switch/case on it without success. I am at a point I just want to carry on and tried the following:

var connState : WFSensorConnectionStatus_t = WF_SENSOR_CONNECTION_STATUS_IDLE
...
if( connState == WF_SENSOR_CONNECTION_STATUS_IDLE){

But it does not compile:

'WFSensorConnectionStatus_t' is not convertible to 'NSObject'

Any workaround? I read to use WFSensorConnectionStatus_t.WF_SENSOR_CONNECTION_STATUS_IDLE or WF_SENSOR_CONNECTION_STATUS_IDLE.value but it does not work in xcode beta-4.

like image 285
Manuel Darveau Avatar asked Jul 25 '14 04:07

Manuel Darveau


People also ask

Can we use Swift enum in Objective-C?

Event though Swift supports string enums they cannot be used in Objective-C, only Int enums are allowed.

What is the difference between creating enum using Ns_enum and using typedef enum?

First, NS_ENUM uses a new feature of the C language where you can specify the underlying type for an enum. In this case, the underlying type for the enum is NSInteger (in plain C it would be whatever the compiler decides, char, short, or even a 24 bit integer if the compiler feels like it).

How do you declare an enum in Objective-C?

Enums are defined by the following the syntax above. typedef NS_ENUM(NSUInteger, MyEnum) { MyEnumValueA, MyEnumValueB, MyEnumValueC, }; You also can set your own raw-values to the enumeration types. typedef NS_ENUM(NSUInteger, MyEnum) { MyEnumValueA = 0, MyEnumValueB = 5, MyEnumValueC = 10, };

What is typedef enum in Objective-C?

A typedef in Objective-C is exactly the same as a typedef in C. And an enum in Objective-C is exactly the same as an enum in C. This declares an enum with three constants kCircle = 0, kRectangle = 1 and kOblateSpheroid = 2, and gives the enum type the name ShapeType.


Video Answer


2 Answers

The workaround to use .value to get the underlying integer doesn't work anymore as of Beta 4, as you said.

Unfortunately an enum is not transferrable to Swift from Objective-C, it needs to be an NS_ENUM.

I have the same setup as you in a project where I need the enum from an Objective-C framework and use it in Swift.

The workaround I did was to create an Objective-C category that contains an NS_ENUM and there I transfer the values from the framework enum to my own NS_ENUM.

Import the category in your bridging header and you should be able to use the enum as you normally would do.

Something like this:

typedef NS_ENUM(NSUInteger, ConnectionStatus) {
    ConnectionStatusIdle
}

- (ConnectionStatus)connectionStatus {
    if [self getConnectionStatus] == WF_SENSOR_CONNECTION_STATUS_IDLE {
        return ConnectionStatusIdle
    }
}

Then you should be able to use it like this:

switch myObject.connectionStatus() {
    case .Idle:
        // do something
        break
}
like image 181
Markus Persson Avatar answered Sep 28 '22 18:09

Markus Persson


Here is the final complete solution:

WFSensorConnection+SensorConnectionEnumCategory.h

:

#import <Foundation/Foundation.h>

#import <WFConnector/WFConnector.h>

@interface WFSensorConnection (SensorConnectionEnumCategory)

typedef NS_ENUM(NSUInteger, ConnectionStatus) {
    ConnectionStatusIdle,
    ConnectionStatusConnecting,
    ConnectionStatusConnected,
    ConnectionStatusInterrupted,
    ConnectionStatusDisconnecting
};

- (ConnectionStatus) swift_connectionStatus;

@end

WFSensorConnection+SensorConnectionEnumCategory.m

:

#import "WFSensorConnection+SensorConnectionEnumCategory.h"

@implementation WFSensorConnection (SensorConnectionEnumCategory)

- (ConnectionStatus) swift_connectionStatus{
    if ( [self connectionStatus] == WF_SENSOR_CONNECTION_STATUS_IDLE ){
        return ConnectionStatusIdle;
    } else if ( [self connectionStatus] == WF_SENSOR_CONNECTION_STATUS_CONNECTING ){
        return ConnectionStatusConnecting;
    } else if ( [self connectionStatus] == WF_SENSOR_CONNECTION_STATUS_CONNECTED ){
        return ConnectionStatusConnected;
    } else if ( [self connectionStatus] == WF_SENSOR_CONNECTION_STATUS_DISCONNECTING ){
        return ConnectionStatusDisconnecting;
    } else if ( [self connectionStatus] == WF_SENSOR_CONNECTION_STATUS_INTERRUPTED ){
        return ConnectionStatusInterrupted;
    }
    return 0;
}

@end

Bridging-Header.h

:

#import "WFSensorConnection+SensorConnectionEnumCategory.h"

Usage:

var sensorConnection: WFSensorConnection?
var connState : ConnectionStatus = ConnectionStatus.Idle
connState = sensorConnection!.swift_connectionStatus()
switch connState {
    case ConnectionStatus.Idle:
...
}
like image 21
Manuel Darveau Avatar answered Sep 28 '22 18:09

Manuel Darveau