Switch 문 외부의 Swift 열거형 관련 값에 액세스하는 방법
고려 사항:
enum Line {
case Horizontal(CGFloat)
case Vertical(CGFloat)
}
let leftEdge = Line.Horizontal(0.0)
let leftMaskRightEdge = Line.Horizontal(0.05)
어떻게 접근할 수 있습니까?lefEdge
스위치 문을 사용하지 않고 직접 연결된 값?
let noIdeaHowTo = leftEdge.associatedValue + 0.5
이건 컴파일도 안 돼요!
이러한 SO 질문을 살펴보았지만 이 문제를 해결할 수 있는 답변이 없는 것 같습니다.
그noIdeaHowTo
위의 비컴파일링 라인은 정말로 하나의 라인이어야 하지만, 왜냐하면associated value
모든 유형이 될 수 있습니다. 어떻게 사용자 코드가 leenum 자체에서 "generic" get 또는 associatedValue 메서드를 작성할 수 있는지조차 알 수 없습니다.
결국 이런 결과를 낳았지만, 정말 역겹고 사례를 추가/수정할 때마다 코드를 다시 확인해야 합니다.
enum Line {
case Horizontal(CGFloat)
case Vertical(CGFloat)
var associatedValue: CGFloat {
get {
switch self {
case .Horizontal(let value): return value
case .Vertical(let value): return value
}
}
}
}
누구 포인터 있어요?
다른 사람들이 지적했듯이 Swift 2에서는 다음과 같은 작업이 가능합니다.
import CoreGraphics
enum Line {
case Horizontal(CGFloat)
case Vertical(CGFloat)
}
let min = Line.Horizontal(0.0)
let mid = Line.Horizontal(0.5)
let max = Line.Horizontal(1.0)
func doToLine(line: Line) -> CGFloat? {
if case .Horizontal(let value) = line {
return value
}
return .None
}
doToLine(min) // prints 0
doToLine(mid) // prints 0.5
doToLine(max) // prints 1
다음과 같이 가드 문을 사용하여 관련 값에 액세스할 수 있습니다.
enum Line {
case Horizontal(Float)
case Vertical(Float)
}
let leftEdge = Line.Horizontal(0.0)
let leftMaskRightEdge = Line.Horizontal(0.05)
guard case .Horizontal(let leftEdgeValue) = leftEdge else { fatalError() }
print(leftEdgeValue)
제 생각에 당신은 당신이 사용하려고 하는 것 같습니다.enum
그것이 의도되지 않은 어떤 것을 위하여.관련 값에 액세스하는 방법은 실제로 다음과 같습니다.switch
당신이 해왔듯이, 그 생각은switch
항상 가능한 각 구성원 사례를 처리합니다.enum
.
의 다양한 구성원enum
서로 다른 관련 값을 가질 수 있습니다(예: 사용자가 가질 수 있음).Diagonal(CGFloat, CGFloat)
그리고.Text(String)
당신의enum Line
), 따라서 관련 값에 액세스하기 전에 처리 중인 사례를 항상 확인해야 합니다.예를 들어, 다음을 생각해 보십시오.
enum Line {
case Horizontal(CGFloat)
case Vertical(CGFloat)
case Diagonal(CGFloat, CGFloat)
case Text(String)
}
var myLine = someFunctionReturningEnumLine()
let value = myLine.associatedValue // <- type?
어떻게 당신은 관련된 가치를 얻을 수 있다고 추정할 수 있습니까?myLine
당신이 상대할 수 있을 때CGFloat
,String
한두 개 CGFloat
s? 이것이 당신이 필요한 이유입니다.switch
어떤 것을 먼저 발견하기 위해case
당신은 가지고 있다.
당신의 특별한 경우에는 당신이 더 나은 것처럼 들릴 수도 있습니다.class
또는struct
위해서Line
그러면 저장할 수도 있습니다.CGFloat
그리고 또한.enum
을 위한 재산.Vertical
그리고.Horizontal
아니면 모델을 할 수도 있고,Vertical
그리고.Horizontal
별도의 클래스로, 포함Line
프로토콜이 되는 것(예:).
if caselet 구문을 사용하여 스위치를 사용하지 않고 관련 값을 가져올 수 있습니다.
enum Messages {
case ping
case say(message: String)
}
let val = Messages.say(message: "Hello")
if case let .say(msg) = val {
print(msg)
}
if caselet 내부의 블록은 enum 값이 .say이면 실행되며, 범위 내의 관련 값이 if 문에서 사용하는 변수 이름으로 지정됩니다.
왜 이것이 불가능한지는 이미 답이 나왔기 때문에, 이것은 단지 조언일 뿐입니다.이렇게 구현해 보는 게 어때요?열거형과 구조체는 모두 값 유형입니다.
enum Orientation {
case Horizontal
case Vertical
}
struct Line {
let orientation : Orientation
let value : CGFloat
init(_ orientation: Orientation, _ value: CGFloat) {
self.orientation = orientation
self.value = value
}
}
let x = Line(.Horizontal, 20.0)
// if you want that syntax 'Line.Horizontal(0.0)' you could fake it like this
struct Line {
let orientation : Orientation
let value : CGFloat
private init(_ orientation: Orientation, _ value: CGFloat) {
self.orientation = orientation
self.value = value
}
static func Horizontal(value: CGFloat) -> Line { return Line(.Horizontal, value) }
static func Vertical(value: CGFloat) -> Line { return Line(.Vertical, value) }
}
let y = Line.Horizontal(20.0)
Swift 2를 사용하면 반사를 사용하여 관련 값(읽기 전용)을 얻을 수 있습니다.
쉽게 하려면 아래 코드를 프로젝트에 추가하고 EVA 관련 프로토콜로 열거형을 확장하기만 하면 됩니다.
public protocol EVAssociated {
}
public extension EVAssociated {
public var associated: (label:String, value: Any?) {
get {
let mirror = Mirror(reflecting: self)
if let associated = mirror.children.first {
return (associated.label!, associated.value)
}
print("WARNING: Enum option of \(self) does not have an associated value")
return ("\(self)", nil)
}
}
}
그런 다음 다음과 같은 코드를 사용하여 .asociated 값에 액세스할 수 있습니다.
class EVReflectionTests: XCTestCase {
func testEnumAssociatedValues() {
let parameters:[EVAssociated] = [usersParameters.number(19),
usersParameters.authors_only(false)]
let y = WordPressRequestConvertible.MeLikes("XX", Dictionary(associated: parameters))
// Now just extract the label and associated values from this enum
let label = y.associated.label
let (token, param) = y.associated.value as! (String, [String:Any]?)
XCTAssertEqual("MeLikes", label, "The label of the enum should be MeLikes")
XCTAssertEqual("XX", token, "The token associated value of the enum should be XX")
XCTAssertEqual(19, param?["number"] as? Int, "The number param associated value of the enum should be 19")
XCTAssertEqual(false, param?["authors_only"] as? Bool, "The authors_only param associated value of the enum should be false")
print("\(label) = {token = \(token), params = \(param)")
}
}
// See http://github.com/evermeer/EVWordPressAPI for a full functional usage of associated values
enum WordPressRequestConvertible: EVAssociated {
case Users(String, Dictionary<String, Any>?)
case Suggest(String, Dictionary<String, Any>?)
case Me(String, Dictionary<String, Any>?)
case MeLikes(String, Dictionary<String, Any>?)
case Shortcodes(String, Dictionary<String, Any>?)
}
public enum usersParameters: EVAssociated {
case context(String)
case http_envelope(Bool)
case pretty(Bool)
case meta(String)
case fields(String)
case callback(String)
case number(Int)
case offset(Int)
case order(String)
case order_by(String)
case authors_only(Bool)
case type(String)
}
위의 코드는 제 프로젝트 https://github.com/evermeer/EVReflection 에서 가져온 것입니다. https://github.com/evermeer/EVReflection
언급URL : https://stackoverflow.com/questions/31359142/how-to-access-a-swift-enum-associated-value-outside-of-a-switch-statement
'code' 카테고리의 다른 글
sql plus의 문자열에서 마지막 문자 제거 (0) | 2023.08.01 |
---|---|
ID 선택기에 jQuery 도트가 있습니까? (0) | 2023.08.01 |
TimeSpan을 형식 "hh:mm:ss"에서 "hh:mm"로 변환 (0) | 2023.08.01 |
MatPaginatorIntl을 사용하는 방법은 무엇입니까? (0) | 2023.07.27 |
window.location을 업데이트하려면 어떻게 해야 합니까?문서를 건너뛰지 않고 해시하시겠습니까? (0) | 2023.07.27 |