如何使用原始类型的CGPoint创建枚举?

时间:2014-06-11 10:53:52

标签: swift

灵感来自this question。 Swift支持使用任何原始类型创建枚举,因此能够使用原始类型的CGPoint创建枚举将会很好。

但是这段代码不会编译

enum MyEnum : CGPoint {
    case Zero
}

有以下错误

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

那么如何使用原始类型的CGPoint声明枚举?

3 个答案:

答案 0 :(得分:36)

给定代码中有两个错误。

第一个是

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)

第二个错误是

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

现在很容易修复,只需为它指定一些字符串文字

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原始类型的枚举


使用它

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­

只有三种类型的文字,因此字符串文字是唯一的选项(除非您希望1.2(1, 2)

答案 1 :(得分:11)

你实际上可以有一个正确的方法。这段代码允许您将CGPoint作为RawValue的{​​{1}}:

enum

答案 2 :(得分:3)

我非常喜欢Bryan Chen的解决方案,但我选择了另一种方案。它并没有真正使用枚举:

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名称。