Подтвердить что ты не робот

Использование не NS_ENUM objective-C enum в swift

Я использую API-интерфейс wahoo fitness, и он определяет следующее objective-C перечисление:

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;

Я не могу найти способ использовать его в swift. Сначала я попытался сделать переключатель/случай без успеха. Я нахожусь в точке, которую просто хочу продолжить, и попробовал следующее:

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

Но он не компилируется:

'WFSensorConnectionStatus_t' is not convertible to 'NSObject'

Любое обходное решение? Я читал использовать WFSensorConnectionStatus_t.WF_SENSOR_CONNECTION_STATUS_IDLE или WF_SENSOR_CONNECTION_STATUS_IDLE.value, но он не работает в xcode beta-4.

4b9b3361

Ответ 1

Обходной путь для использования .value для получения базового целого не работает больше с Beta 4, как вы сказали.

К сожалению, enum не переносится в Swift из Objective-C, он должен быть NS_ENUM.

У меня такая же настройка, как и в проекте, где мне нужна enum из рамки Objective-C и использовать ее в Swift.

Обходной путь, который я сделал, заключался в создании категории Objective-C, содержащей NS_ENUM, и я переношу значения из фреймворка enum в свой собственный NS_ENUM.

Импортируйте категорию в заголовок моста, и вы сможете использовать enum, как обычно.

Что-то вроде этого:

typedef NS_ENUM(NSUInteger, ConnectionStatus) {
    ConnectionStatusIdle
}

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

Затем вы сможете использовать его следующим образом:

switch myObject.connectionStatus() {
    case .Idle:
        // do something
        break
}

Ответ 2

Импорт контейнеров в стиле C в Swift как UInt32. Поэтому вы можете сделать что-то вроде:

let state = unsafeBitCast(WF_SENSOR_CONNECTION_STATUS_IDLE, UInt32.self)
if state == unsafeBitCast(WF_SENSOR_CONNECTION_STATUS_IDLE, UInt32.self) {
    //do something
}

Обновление: в Swift 2.1 (Xcode 7.1 beta 2) все перечисления C-стиля соответствуют Equatable, и теперь вы можете использовать его как:

let state = WF_SENSOR_CONNECTION_STATUS_IDLE
if state == WF_SENSOR_CONNECTION_STATUS_IDLE {
    //do something
}

Прибыль:)

Ответ 3

Вот окончательное полное решение:

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"

Использование:

var sensorConnection: WFSensorConnection?
var connState : ConnectionStatus = ConnectionStatus.Idle
connState = sensorConnection!.swift_connectionStatus()
switch connState {
    case ConnectionStatus.Idle:
...
}

Ответ 4

Обратите внимание, что существует тип CoreFoundation, который похож на NS_ENUM, называемый CF_ENUM. Я использовал его в своих фреймворках, в основном C. И да, Swift действительно переводит его в перечисление Swift.

Существует также нечто подобное для NS_OPTIONS, называемое CF_OPTIONS.