2014-06-11 2 views
25

this question에서 영감을 얻었습니다. 원시 형식을 사용하여 열거 형을 신속하게 만들 수 있으므로 원시 형식의 CGPoint로 열거 형을 만들면 좋습니다.CGPoint의 원시 형식으로 열거 형을 만드는 방법은 무엇입니까?

하지만이 코드는 어떻게 CGPoint의 원시 유형을 열거를 선언하는 오류

<REPL>:50:15: error: raw type 'CGPoint' is not convertible from any literal 
enum MyEnum : CGPoint { 
      ^
<REPL>:51:10: error: enum cases require explicit raw values when the raw type is not integer literal convertible 
    case Zero 
    ^

을 다음과 같이

enum MyEnum : CGPoint { 
    case Zero 
} 

를 컴파일되지 않습니다?

답변

34

주어진 코드에 두 가지 오류가 있습니다.

첫 번째

error: raw type 'CGPoint' is not convertible from any literal 
    enum MyEnum : CGPoint { 

그래서 우리는 그것을 준수하여이 문자열에서 변환 문자 만들기 위해 CGPoint을 확장하는 것입니다 해결하기 위해 문자

한 가지 방법에서 CGPoint 컨버터블 할 필요가있다 StringLiteralConvertible

extension CGPoint : StringLiteralConvertible { 
    static func convertFromStringLiteral(value: String) -> CGPoint { 
     return NSPointFromString(value) // CGPointFromString on iOS 
    } 

    static func convertFromExtendedGraphemeClusterLiteral(value: String) -> CGPoint { 
     return NSPointFromString(value) // CGPointFromString on iOS 
    } 
} 

문자열 리터럴에서 CGPoint를 만들 수 있습니다!

var p : CGPoint = "2,3" 
println(p) // print (2.0,3.0) 

번째 오류는 현재 수정 그냥 리터럴

enum MyEnum : CGPoint { 
    case Zero = "0, 0" 
    case One = "1, 1" 
    case MagicPoint = "0, 42" 
} 

println(MyEnum.Zero.toRaw()) // (0.0,0.0) 
println(MyEnum.One.toRaw()) // (1.0,1.0) 
println(MyEnum.MagicPoint.toRaw()) // (0.0,42.0) 

일부 문자열을 할당하고 지금은 CGPoint 원시 유형을 열거을 가지고 쉽게

error: enum cases require explicit raw values when the raw type is not integer literal convertible 
     case Zero 
     ^

입니다


그것은 불가능처럼

if let p = MyEnum.fromRaw(CGPoint(x:0, y:42)) { 
    switch (p) { 
    case .Zero: 
     println("p is (0, 0)") 
     break 
    case .One: 
     println("p is (1, 1)") 
     break 
    case .MagicPoint: 
     println("p is magic point") 
     break 
    } 
} 

// print "p is magic point" 

튜플에서 CGPoint를 만들 좋을 것이다, 그러나, 보인다. grammar

literal → integer-literal­ floating-point-literal­ string-literal­ 

에서

가 문자 그대로의 세 가지 유형, 그래서

+2

경우 제로 ='같은 튜플에서 만드는 더 좋은 것 (0, 0)'하지만 난 알아낼 방법 수 없다 아직해라. –

+0

'switch '와 함께 자동으로 작동할까요, 아니면 패턴 매칭 연산자를 오버라이드해야할까요? – Sulthan

+0

@Sulthan 내 업데이트를 참조하십시오 –

3

(당신이 (1, 2)1.2을 원하지 않는다면) 문자열 리터럴 여기에 옵션 만 정말 브라이언 첸의 솔루션과 같은 그러나 나는 하나의 대안으로왔다.이제

extension CGPoint : RawRepresentable, Equatable { 
    typealias RawType = (CGFloat, CGFloat) 

    static let Zero = CGPointZero 
    static let One = CGPoint(x: 1.0, y: 1.0) 
    static let MagicPoint = CGPoint(x: 42.0, y: 0.0) 

    static func fromRaw(raw: RawType) -> CGPoint? { 
     return CGPoint(x: raw.0, y: raw.1) 
    } 

    func toRaw() -> RawType { 
     return (x, y) 
    } 
} 

우리는 모두 "원시"작업을 수행 할 수 있습니다 :

var p = CGPoint.fromRaw((10, 20)) //from tuple 

우리는 또한 switch 사용할 수 있습니다 : 그것은 정말 열거 사용하지 않는 그러나

switch (p) { 
case CGPoint.Zero: 
    println("p is (0, 0)") 
case CGPoint.One: 
    println("p is (1, 1)") 
case CGPoint.MagicPoint: 
    println("p is (42, 0)") 
case CGPoint(x: 0, y: 10): 
    println("p is (0, 10)") 
default: 
    println("Something else") 
} 

을, 당신을 default 사례가 필요하며 짧은 .Zero 이름을 사용할 수 없습니다.

9

실제로 적절한 방법이 있습니다. 이것은 당신이 같은 CGPoint을 가질 수 코드입니다 RawValueenum의 :

enum MyPointEnum { 
    case zero 
} 

extension MyPointEnum: RawRepresentable { 
    typealias RawValue = CGPoint 

    init?(rawValue: CGPoint) { 
     if rawValue == CGPoint.zero { 
      self = .zero 
     } else { 
      return nil 
     } 
    } 

    var rawValue: CGPoint { 
     switch self { 
     case .zero: 
      return CGPoint.zero 
     } 
    } 
} 

print(MyPointEnum.zero.rawValue) //prints "(0.0, 0.0)\n" 
관련 문제