Неправильная переопределение rawValue в сборке выпуска
У меня смешанный проект, и я столкнулся с интересной проблемой. Есть перечисление, определенное в obj-c
typedef NS_ENUM (NSUInteger, ABCCategory) {
ABCCategoryFirst,
ABCCategorySecond
};
Далее есть файл swift, в котором определено расширение
extension ABCCategory: RawRepresentable {
public typealias RawValue = String
public init(rawValue: RawValue) {
switch rawValue {
case "first":
self = .first
case "second":
self = .second
default:
self = .first
}
}
public var rawValue: RawValue {
get {
switch self {
case .first:
return "first"
case .second:
return "second"
}
}
}
}
Все отлично работает в конфигурации Debug, но когда я переключаюсь на Release, он не собирается, говоря: неверное объявление "rawValue" Я попытался удалить typealias, заменив RawValue на String (чтобы протокол мог неявно угадать значение), делая необязательный конструктор, как в протоколе (и неявно развернутый необязательно также) - нет пути.
Я понимаю, что расширение Int enum со строкой немного странно, но почему оно перестает собираться в Release и работает абсолютно идеально в Debug?
Есть ли какой-то другой механизм обработки перечислений / классов / расширений для конфигурации выпуска?
1 ответ
Синтаксис необработанных значений для перечислений в Swift - это просто сокращение для соответствия протоколу RawRepresentable. Это легко добавить вручную, если вы хотите использовать неподдерживаемые типы в качестве необработанных значений. Источник
Я не уверен, почему это работает в отладке, потому что когда вы создаете типизированное перечисление, вы уже "соответствуете" RawRepresentable
, Поэтому, когда вы создаете NS_ENUM
он импортируется так быстро:
public enum ABCCategory : UInt {
case first
case second
}
Это означает, что это уже соответствует RawRepresentable
, Исправление может быть достигнуто двумя способами, один в Swift и в Objective-C
В Swift мы просто удаляем RawRepresentable
и изменить rawValue
в stringValue
, а также RawValue
в String
:
extension ABCCategory {
var stringValue: String {
switch self {
case .first: return "first"
case .second: return "second"
}
}
init(_ value: String) {
switch value {
case "first":
self = .first
case "second":
self = .second
default:
self = .first
}
}
}
Или вы можете просто изменить Objective-C, чтобы использовать NS_TYPED_ENUM
, Некоторая информация здесь. Однако это изменит ваше перечисление на struct
.час
typedef NSString *ABCCategory NS_TYPED_ENUM;
extern ABCCategory const ABCCategoryFirst;
extern ABCCategory const ABCCategorySecond;
.m
ABCCategory const ABCCategoryFirst = @"first";
ABCCategory const ABCCategorySecond = @"second";
Это будет импортировано с помощью swift так:
public struct ABCCategory : Hashable, Equatable, RawRepresentable {
public init(rawValue: String)
}
public static let first: ABCCategory
public static let second: ABCCategory