How to make a Swift String enum available in Objective-C?

前端 未结 10 2106
情深已故
情深已故 2020-12-01 07:09

I have this enum with String values, which will be used to tell an API method that logs to a server what kind of serverity a message has. I\'m using Swift 1.2,

相关标签:
10条回答
  • 2020-12-01 07:47

    From the Xcode 6.3 release notes (emphasis added):

    Swift Language Enhancements

    ...
    Swift enums can now be exported to Objective-C using the @objc attribute. @objc enums must declare an integer raw type, and cannot be generic or use associated values. Because Objective-C enums are not namespaced, enum cases are imported into Objective-C as the concatenation of the enum name and case name.

    0 讨论(0)
  • 2020-12-01 07:47

    Here is work around if you really want to achieve the goal. However, you can access the enum values in objects that Objective C accepts, not as actual enum values.

    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()
        }
    }
    

    To call :

    NSString *debugRawValue = [LogSeverityBridge Debug]
    
    0 讨论(0)
  • 2020-12-01 07:50

    If you don't mind to define the values in (Objective) C, you can use the NS_TYPED_ENUM macro to import constants in Swift.

    For example:

    .h file

    typedef NSString *const ProgrammingLanguage NS_TYPED_ENUM;
    
    FOUNDATION_EXPORT ProgrammingLanguage ProgrammingLanguageSwift;
    FOUNDATION_EXPORT ProgrammingLanguage ProgrammingLanguageObjectiveC;
    

    .m file

    ProgrammingLanguage ProgrammingLanguageSwift = "Swift";
    ProgrammingLanguage ProgrammingLanguageObjectiveC = "ObjectiveC";
    

    In Swift, this is imported as a struct as such:

    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 }
    }
    

    Although the type is not bridged as an enum, it feels very similar to one when using it in Swift code.

    You can read more about this technique in the "Interacting with C APIs" of the Using Swift with Cocoa and Objective-C documentation

    0 讨论(0)
  • 2020-12-01 07:54

    One of the solutions is to use the RawRepresentable protocol.

    It's not ideal to have to write the init and rawValue methods but that allows you to use this enum as usual in both Swift and 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:
                    return nil
            }
        }
    }
    
    0 讨论(0)
提交回复
热议问题