Objective-C에서 Swift String 열거 형을 사용하는 방법은 무엇입니까?
이 열거 형 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 원시 유형이 아닌 정수 유형이 아닙니다.
정수만 Swift에서 Objective-C로 변환 할 수있는 말하는 곳을 찾을 수 있습니다. 이것이 사실입니까? Objective-C에서 이와 같은 것을 제공하는 방법에 대한 모범 사례 제안이 있습니까?
로부터 엑스 코드 6.3 릴리스 노트 (강조는 추가) :
Swift 언어 향상
...
@objc 속성을 사용하여 Swift 열거 형을 Objective-C로 정렬 할 수 있습니다. @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
struct Constants {
static let types: [LogSeverity: String] = [
.debug: "DEBUG",
.info: "INFO",
.warn: "WARN",
.error: "ERROR"
]
}
public typealias RawValue = String
public var rawValue: RawValue {
guard let value = Constants.routes[self] else {
fatalError("constants definition is missing: \(self)")
}
return value
}
public init?(rawValue: RawValue) {
guard let severity = Constants.types.first(where: { $0.value == rawValue }) else {
return nil
}
self = severity.key
}
}
작동하는 솔루션이 있습니다.
@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]
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"
}
}
}
(목표) 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 코드에서 사용할 때 유형 과 매우 유사합니다.
이 기술에 대한 자세한 내용은 Cocoa 및 Objective-C에서 Swift 사용 문서 의 "C API와 상호 작용"에서 확인할 수 있습니다.
이 내 사용 사례입니다.
- 할 수있을 때마다 하드 코딩 될 때마다 준비를 코딩 할 때 경고를받습니다.
- 백엔드에서 오는 고정 및 값 목록이 있으며, 이는 nil 일 수도 있습니다.
다음은 하드 코딩 된 코드가 전혀없고 누락 된 값을 지원하며 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"
}
}
}
Swift에서 .string
열거 형 ()에 사용할 수 있습니다 .rawValue
. Objective-C에서 다음을 사용할 수 있습니다.[ServiceProvider FieldNameToString:enumValue];
개인 Inner
열거 형을 만들 수 있습니다 . 구현은 약간의 반복 가능하지만 명확하고 신뢰할 수 있습니다. 항상 동일하게 보이는 1 줄 rawValue
, 2 줄 init
. 에 해당 Inner
하는 "외부"를 반환하는 메서드가 해당 반대의 경우도 마찬가지입니다.
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
}
}
}
}
'ProgramingTip' 카테고리의 다른 글
Microsoft SQL Server에서 데이터베이스 삭제 및 재생성 (0) | 2020.12.14 |
---|---|
키 값을 사용하고 해당 값이없는 Python에서 사전 초기화 (0) | 2020.12.14 |
장고 : 사용 (0) | 2020.12.14 |
레일스 POST, PUT, GET (0) | 2020.12.14 |
JavaScript의 요소를 프로그래밍 방식으로 클릭하면 얼마나 많이 사용합니까? (0) | 2020.12.14 |