Как сделать перечисление 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?
Ответы
Ответ 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, которое возвращает строку, основанную на текущем значении перечисления.