Ich habe diese Aufzählung mit String
Werten, die verwendet werden, um einer API-Methode, die bei einem Server protokolliert, mitzuteilen, welche Art von Serverität eine Nachricht hat. Ich verwende Swift 1.2, damit Aufzählungen Objective-C zugeordnet werden können
@objc enum LogSeverity : String {
case Debug = "DEBUG"
case Info = "INFO"
case Warn = "WARN"
case Error = "ERROR"
}
Ich bekomme den Fehler
@objc enum raw type String ist kein ganzzahliger Typ
Ich habe nirgendwo etwas gefunden, das besagt, dass nur ganze Zahlen von Swift nach Objective-C übersetzt werden können. Ist das der Fall? Wenn ja, hat jemand einen Best-Practice-Vorschlag, wie so etwas in Objective-C verfügbar gemacht werden kann?
quelle
Eine der Lösungen besteht darin, das
RawRepresentable
Protokoll zu verwenden.Es ist nicht ideal, die Methoden init und rawValue schreiben zu müssen, aber damit können Sie diese Aufzählung wie gewohnt sowohl in Swift als auch in Objective-C verwenden.
@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: return nil } } }
quelle
[LogSeverity: String]
und dann können die MethodenrawValue
undinit?
durch eine einzelne Zeile definiert werden.LogSeverity
die durchString
s roh darstellbar ist , und Sie einmal ein Wörterbuch vom Typ definieren[LogSeverity: String]
, dann ist der rawValue einfachmyDictionary[self]
und der Init istself = myDictionary.first(where: { $0.value == rawValue })
Hier ist eine Lösung, die funktioniert.
@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" } } }
quelle
name()
Funktion in Objective-C aufgerufen?name()
in objc anrufenHier ist eine Lösung, wenn Sie das Ziel wirklich erreichen möchten. Sie können jedoch auf die Aufzählungswerte in Objekten zugreifen, die von Objective C akzeptiert werden, nicht als tatsächliche Aufzählungswerte.
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() } }
Anrufen :
NSString *debugRawValue = [LogSeverityBridge Debug]
quelle
variables
vom Typ LogSeverity haben können, aber ansonsten OK.@objcMembers public class LogSeverityBridge: NSObject { static func debug() -> String { return TravelerProtectionLevel.premium.rawValue }
Wenn es Ihnen nichts ausmacht, die Werte in (Ziel) C zu definieren, können Sie das
NS_TYPED_ENUM
Makro verwenden, um Konstanten in Swift zu importieren.Zum Beispiel:
.h Datei
typedef NSString *const ProgrammingLanguage NS_TYPED_ENUM; FOUNDATION_EXPORT ProgrammingLanguage ProgrammingLanguageSwift; FOUNDATION_EXPORT ProgrammingLanguage ProgrammingLanguageObjectiveC;
.m Datei
ProgrammingLanguage ProgrammingLanguageSwift = "Swift"; ProgrammingLanguage ProgrammingLanguageObjectiveC = "ObjectiveC";
In Swift wird dies
struct
als solches importiert :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 } }
Obwohl der Typ nicht als überbrückt ist
enum
, fühlt er sich einem sehr ähnlich, wenn er in Swift-Code verwendet wird.Weitere Informationen zu dieser Technik finden Sie in der Dokumentation "Interaktion mit C-APIs" in der Dokumentation " Verwenden von Swift mit Kakao" und "Objective-C"
quelle
Code für Xcode 8 unter Verwendung der Tatsache, dass dies
Int
funktioniert, andere Methoden jedoch nicht Objective-C ausgesetzt sind. Das ist ziemlich schrecklich wie es aussieht ...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" } } }
quelle
Dies ist mein Anwendungsfall:
Hier ist meine Lösung, die überhaupt keine fest codierten Zeichenfolgen enthält, fehlende Werte unterstützt und sowohl in Swift als auch in Obj-C elegant verwendet werden kann:
@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 } } }
quelle
[InventoryItemType fromString:]
von Objective-C verwenden: Es gibt den Fehler "Empfängertyp 'InventoryItemType' ist keine Objective-C-Klasse"public enum TrackingValue { case constant(String) case customVariable(name: String) case defaultVariable(DefaultVariable) public enum DefaultVariable { case advertisingId case advertisingTrackingEnabled case appVersion case connectionType case interfaceOrientation case isFirstEventAfterAppUpdate case requestQueueSize case adClearId } }
Was ist der beste Weg, um es als ObjC-Aufzählung zu sehen? Danke im Voraus!class InventoryItemTypeParser: NSObject { @objc static func fromString(_ string: String?) -> InventoryItemType { return InventoryItemType.fromString(string) } }
Folgendes habe ich mir ausgedacht. In meinem Fall war diese Aufzählung im Zusammenhang mit Informationen für eine bestimmte Klasse
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" } } }
Von Swift aus können Sie
.string
eine Aufzählung verwenden (ähnlich wie.rawValue
). In Objective-C können Sie verwenden[ServiceProvider FieldNameToString:enumValue];
quelle
Sie können eine private
Inner
Aufzählung erstellen . Die Implementierung ist etwas wiederholbar, aber klar und einfach. 1 ZeilerawValue
, 2 Zeileninit
, die immer gleich aussehen. DasInner
hat eine Methode, die das "äußere" Äquivalent zurückgibt und umgekehrt.Hat den zusätzlichen Vorteil, dass Sie den Enum-Fall im
String
Gegensatz zu anderen Antworten hier direkt einem zuordnen können .Wenn Sie wissen, wie Sie das Wiederholbarkeitsproblem mit Vorlagen lösen können, können Sie gerne auf dieser Antwort aufbauen. Ich habe momentan keine Zeit, mich damit zu beschäftigen.
@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 } } } }
quelle
Ich denke, @Remis Antwort stürzt in einigen Situationen ab, da ich Folgendes hatte:
Screesshot meines Fehlers . Also poste ich meine Ausgabe für @Remis Antwort:
@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: return nil } } }
quelle