목표-C에서 스위프트 스트링 열거를 사용할 수 있도록 하는 방법?
나는 이 열거를 가지고 있습니다.String
values - 서버에 로그를 기록하는 API 메서드에 메시지의 서버 유형을 지정하는 데 사용됩니다.저는 스위프트 1.2를 사용하고 있기 때문에 enum을 Objective-C에 매핑할 수 있습니다.
@objc enum LogSeverity : String {
case Debug = "DEBUG"
case Info = "INFO"
case Warn = "WARN"
case Error = "ERROR"
}
오류가 납니다.
@objc 열거 원시 유형 문자열이 정수 유형이 아닙니다.
스위프트에서 Objective-C로 정수만 번역할 수 있다는 곳을 찾지 못했습니다.이런 경우입니까?그렇다면 Objective-C에서 이와 같은 것을 사용할 수 있도록 하는 방법에 대한 모범 사례 제안이 있는 사람이 있습니까?
해결책 중 하나는 다음을 사용하는 것입니다.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:
return nil
}
}
}
Xcode 6.3 릴리즈 노트(강조사항 추가)에서 다음을(를)
빠른 언어 향상
...
이제 @objc 특성을 사용하여 스위프트 엔움을 Objective-C로 내보낼 수 있습니다.@objcenums는 정수 원시 유형을 선언해야 하며, 일반적이거나 관련 값을 사용할 수 없습니다.Objective-Cenums는 namespatched가 아니기 때문에 열거형 사례는 열거형 이름과 사례 이름의 연결로 Objective-C로 가져옵니다.
여기에 효과적인 해결책이 있습니다.
@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
macro에서 Swift의 상수를 가져옵니다.
예를 들어,
.h 파일
typedef NSString *const ProgrammingLanguage NS_TYPED_ENUM;
FOUNDATION_EXPORT ProgrammingLanguage ProgrammingLanguageSwift;
FOUNDATION_EXPORT ProgrammingLanguage ProgrammingLanguageObjectiveC;
.m파일
ProgrammingLanguage ProgrammingLanguageSwift = @"Swift";
ProgrammingLanguage ProgrammingLanguageObjectiveC = @"ObjectiveC";
스위프트에서 이것은 다음과 같이 수입됩니다.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
, 스위프트 코드로 사용했을 때와 매우 유사한 느낌이 듭니다.
이 기법에 대한 자세한 내용은 관련 목표-C 상수 그룹화에서 확인할 수 있습니다.
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"
}
}
}
사용 사례는 다음과 같습니다.
- 가능할 때마다 하드 코딩된 문자열을 사용하지 않으므로 변경할 때 컴파일 경고가 표시됩니다.
- 백엔드에서 오는 String 값의 고정된 목록이 있습니다. 이 목록은 0일 수도 있습니다.
하드 코딩된 Strings가 전혀 포함되지 않고 누락된 값을 지원하며 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
}
}
}
이것이 제가 생각해낸 것입니다.제 경우 이 열거는 특정 클래스에 대한 정보를 제공하는 상황에 있었습니다.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"
}
}
}
스위프트에서 사용할 수 있습니다..string
(와 유사한) 열거적으로.rawValue
). Objective-C 에서 사용할 수 있습니다.[ServiceProvider FieldNameToString:enumValue];
개인 정보를 생성할 수 있습니다.Inner
enum. 구현은 약간 반복 가능하지만 명확하고 쉽습니다. 1줄rawValue
, 2줄init
, 항상 똑같아 보이잖아요. 그.Inner
는 "outer" 등가를 반환하는 방법을 가지고 있으며, 그 반대의 경우에는 versa을 반환합니다.
열거형 사례를 에 직접 매핑할 수 있는 추가 이점이 있습니다.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
}
}
}
}
제 생각에 @Remi의 답변은 제가 했던 것처럼 어떤 상황에 따라 저는 이렇게 생각합니다.
내 오류는 스크린샷입니다. 그래서 나는 @Remi의 답변을 위해 내 판을 올립니다.
@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
}
}
}
언급URL : https://stackoverflow.com/questions/30480338/how-to-make-a-swift-string-enum-available-in-objective-c
'programing' 카테고리의 다른 글
(dir/b > 파일)에 해당합니다.txt) PowerShell에서 (0) | 2023.10.22 |
---|---|
TextView BOLD에서 특정 텍스트를 만드는 방법 (0) | 2023.10.22 |
스위프트 : 캐릭터의 시작부터 마지막 인덱스까지 하위 문자열을 얻는 방법 (0) | 2023.10.22 |
MYSQL - 각 테이블의 행 개수 수 (0) | 2023.10.22 |
판다의 다중 인덱스 정렬 (0) | 2023.10.22 |