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

Как сделать перечисление Swift String доступным в Objective-C?

У меня есть это перечисление со значениями String, которые будут использоваться, чтобы сообщить API-методу, который регистрируется на сервере, какой сервер имеет сообщение. Я использую Swift 1.2, поэтому перечисления могут быть сопоставлены с Objective-C

@objc enum LogSeverity : String {
    case Debug = "DEBUG"
    case Info = "INFO"
    case Warn = "WARN"
    case Error = "ERROR"
}

Я получаю сообщение об ошибке

@objc enum raw type Строка не является целым типом

Мне не удалось найти нигде, где говорится, что только целые числа могут быть переведены в Objective-C из Swift. Это так? Если да, то есть ли у кого-нибудь лучшее предложение о том, как сделать что-то подобное в Objective-C?

4b9b3361

Ответ 1

Из примечания к выпуску Xcode 6.3 (выделено мной):

Быстрые улучшения языка

...
Теперь swift перечисления можно экспортировать в Objective-C с помощью @objc атрибут. @objc enums должен объявить целочисленный тип raw и не может быть общие или используемые связанные значения. Потому что Objective-C перечисления не имена, экземпляры перечисления импортируются в Objective-C в качестве конкатенация имени перечисления и имени имени.

Ответ 2

Одним из решений является использование протокола RawRepresentable.

Не рекомендуется писать методы init и rawValue, но это позволяет использовать это перечисление, как обычно, в Swift и Objective-C.

@objc public enum LogSeverity: Int, RawRepresentable {
    case Debug
    case Info
    case Warn
    case Error

    public typealias RawValue = String

    public var rawValue: RawValue {
        switch self {
            case .Debug:
                return "DEBUG"
            case .Info:
                return "INFO"
            case .Warn:
                return "WARN"
            case .Error:
                return "ERROR"
        }
    }

    public init?(rawValue: RawValue) {
        switch rawValue {
            case "DEBUG":
                self = .Debug
            case "INFO":
                self = .Info
            case "WARN":
                self = .Warn
            case "ERROR":
                self = .Error
            default:
                self = .Debug
        }
    }
}

Ответ 3

Здесь работает решение.

@objc public enum ConnectivityStatus: Int {
    case Wifi
    case Mobile
    case Ethernet
    case Off

    func name() -> String {
        switch self {
        case .Wifi: return "wifi"
        case .Mobile: return "mobile"
        case .Ethernet: return "ethernet"
        case .Off: return "off"
        }
    }
}

Ответ 4

Вот работа, если вы действительно хотите достичь цели. Однако вы можете получить доступ к значениям перечисления в объектах, которые Objective C принимает, а не как фактические значения перечисления.

enum LogSeverity : String {

    case Debug = "DEBUG"
    case Info = "INFO"
    case Warn = "WARN"
    case Error = "ERROR"

    private func string() -> String {
        return self.rawValue
    }
}

@objc
class LogSeverityBridge: NSObject {

    class func Debug() -> NSString {
        return LogSeverity.Debug.string()
    }

    class func Info() -> NSString {
        return LogSeverity.Info.string()
    }

    class func Warn() -> NSString {
        return LogSeverity.Warn.string()
    }

    class func Error() -> NSString {
        return LogSeverity.Error.string()
    }
}

Для вызова:

NSString *debugRawValue = [LogSeverityBridge Debug]

Ответ 5

Код для Xcode 8, используя тот факт, что Int работает, но другие методы не подвергаются Objective-C. Это довольно ужасно, поскольку оно стоит...

class EnumSupport : NSObject {
    class func textFor(logSeverity severity: LogSeverity) -> String {
        return severity.text()
    }
}

@objc public enum LogSeverity: Int {
    case Debug
    case Info
    case Warn
    case Error

    func text() -> String {
        switch self {
            case .Debug: return "debug"
            case .Info: return "info"
            case .Warn: return "warn"
            case .Error: return "error"
        }
    }
}

Ответ 6

Вот что я придумал. В моем случае это перечисление было в контексте, предоставляющем информацию для определенного класса, ServiceProvider.

class ServiceProvider {
    @objc enum FieldName : Int {
        case CITY
        case LATITUDE
        case LONGITUDE
        case NAME
        case GRADE
        case POSTAL_CODE
        case STATE
        case REVIEW_COUNT
        case COORDINATES

        var string: String {
            return ServiceProvider.FieldNameToString(self)
        }
    }

    class func FieldNameToString(fieldName:FieldName) -> String {
        switch fieldName {
        case .CITY:         return "city"
        case .LATITUDE:     return "latitude"
        case .LONGITUDE:    return "longitude"
        case .NAME:         return "name"
        case .GRADE:        return "overallGrade"
        case .POSTAL_CODE:  return "postalCode"
        case .STATE:        return "state"
        case .REVIEW_COUNT: return "reviewCount"
        case .COORDINATES:  return "coordinates"
        }
    }
}

Из Swift вы можете использовать .string в перечислении (аналогично .rawValue). Из Objective-C вы можете использовать [ServiceProvider FieldNameToString:enumValue];

Ответ 7

У меня был прецедент, где мне все еще нужно было связать строковое значение со стороны Swift. Я написал о своем решении здесь: https://medium.com/@oscarcortes/using-swift-string-enums-in-objective-c-f6683da5b92e По существу, вы можете добавить метод в перечисление Swift, которое возвращает строку, основанную на текущем значении перечисления.