この列挙型には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 Stringは整数型ではありません
SwiftからObjective-Cに変換できるのは整数のみであると言う場所を見つけることができませんでした。これは事実ですか?もしそうなら、Objective-Cでこのようなものを利用可能にする方法についてのベストプラクティスの提案はありますか?
Xcode 6.3リリースノート (強調を追加)から:
Swift言語の機能強化
...
Swift列挙型は、@ objc属性を使用してObjective-Cにエクスポートできるようになりました。 @objc列挙は整数の生の型を宣言する必要があり、ジェネリックまたは関連する値を使用することはできません。 Objective-C列挙型は名前空間ではないため、列挙型ケースは、列挙名とケース名の連結としてObjective-Cにインポートされます。
解決策の1つは、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
}
}
}
これが有効なソリューションです。
@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"
}
}
}
目標を本当に達成したい場合の回避策を次に示します。ただし、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]
(Objective)Cで値を定義することを気にしない場合は、NS_TYPED_ENUM
マクロは、Swiftに定数をインポートします。
例えば:
。hファイル
typedef NSString *const ProgrammingLanguage NS_TYPED_ENUM;
FOUNDATION_EXPORT ProgrammingLanguage ProgrammingLanguageSwift;
FOUNDATION_EXPORT ProgrammingLanguage ProgrammingLanguageObjectiveC;
。mファイル
ProgrammingLanguage ProgrammingLanguageSwift = "Swift";
ProgrammingLanguage ProgrammingLanguageObjectiveC = "ObjectiveC";
Swiftでは、これはstruct
としてインポートされます:
struct ProgrammingLanguage: RawRepresentable, Equatable, Hashable {
typealias RawValue = String
init(rawValue: RawValue)
var rawValue: RawValue { get }
static var Swift: ProgrammingLanguage { get }
static var objectiveC: ProgrammingLanguage { get }
}
この型はenum
としてブリッジされていませんが、Swiftコードで使用する場合と非常によく似ています。
Int
は機能するが、他のメソッドはObjective-Cに公開されないという事実を使用したXcode 8のコード。これはかなり恐ろしいことです...
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"
}
}
}
これは私のユースケースです:
ハードコードされた文字列をまったく含まず、欠損値をサポートし、SwiftとObj-Cの両方でエレガントに使用できる私のソリューションです。
@objc enum InventoryItemType: Int {
private enum StringInventoryItemType: String {
case vial
case syringe
case crystalloid
case bloodProduct
case supplies
}
case vial
case syringe
case crystalloid
case bloodProduct
case supplies
case unknown
static func fromString(_ string: String?) -> InventoryItemType {
guard let string = string else {
return .unknown
}
guard let stringType = StringInventoryItemType(rawValue: string) else {
return .unknown
}
switch stringType {
case .vial:
return .vial
case .syringe:
return .syringe
case .crystalloid:
return .crystalloid
case .bloodProduct:
return .bloodProduct
case .supplies:
return .supplies
}
}
var stringValue: String? {
switch self {
case .vial:
return StringInventoryItemType.vial.rawValue
case .syringe:
return StringInventoryItemType.syringe.rawValue
case .crystalloid:
return StringInventoryItemType.crystalloid.rawValue
case .bloodProduct:
return StringInventoryItemType.bloodProduct.rawValue
case .supplies:
return StringInventoryItemType.supplies.rawValue
case .unknown:
return nil
}
}
}
プライベートInner
enumを作成できます。実装は少し繰り返し可能ですが、明確で簡単です。 1行rawValue
、2行init
、これらは常に同じように見えます。 Inner
には、同等の「外部」を返すメソッドがあり、逆も同様です。
ここにある他の回答とは異なり、enumケースをString
に直接マップできるという追加の利点があります。
テンプレートで再現性の問題を解決する方法を知っているなら、この答えに基づいて構築することを歓迎してください。私は今、それと交流する時間がありません。
@objc enum MyEnum: NSInteger, RawRepresentable, Equatable {
case
option1,
option2,
option3
// MARK: RawRepresentable
var rawValue: String {
return toInner().rawValue
}
init?(rawValue: String) {
guard let value = Inner(rawValue: rawValue)?.toOuter() else { return nil }
self = value
}
// MARK: Obj-C support
private func toInner() -> Inner {
switch self {
case .option1: return .option1
case .option3: return .option3
case .option2: return .option2
}
}
private enum Inner: String {
case
option1 = "option_1",
option2 = "option_2",
option3 = "option_3"
func toOuter() -> MyEnum {
switch self {
case .option1: return .option1
case .option3: return .option3
case .option2: return .option2
}
}
}
}
これが私が思いついたものです。私の場合、この列挙型は特定のクラス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];