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

Bry*_*hen 26 swift

灵感来自这个问题.Swift支持使用任何原始类型创建枚举,因此能够使用原始类型的CGPoint创建枚举将会很好.

但是这段代码不会编译

enum MyEnum : CGPoint {
    case Zero
}
Run Code Online (Sandbox Code Playgroud)

有以下错误

<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
     ^
Run Code Online (Sandbox Code Playgroud)

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

Bry*_*hen 36

给定代码中有两个错误.

第一个是

error: raw type 'CGPoint' is not convertible from any literal
    enum MyEnum : CGPoint {
Run Code Online (Sandbox Code Playgroud)

所以我们需要从文字中创建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
    }
}
Run Code Online (Sandbox Code Playgroud)

我们现在可以从字符串文字创建CGPoint!

var p : CGPoint = "2,3"
println(p) // print (2.0,3.0)
Run Code Online (Sandbox Code Playgroud)

第二个错误是

error: enum cases require explicit raw values when the raw type is not integer literal convertible
        case Zero
         ^
Run Code Online (Sandbox Code Playgroud)

这很容易解决,只需为它分配一些字符串文字

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)
Run Code Online (Sandbox Code Playgroud)

现在你有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"
Run Code Online (Sandbox Code Playgroud)

从元组创建CGPoint会更好,但看起来不可能.

语法

literal ? integer-literal­  floating-point-literal­  string-literal­
Run Code Online (Sandbox Code Playgroud)

只有三种类型的文字,所以string-literal是这里唯一的选择(除非你想1.2成为(1, 2))

  • 从像`case Zero =(0,0)`这样的元组创建会更好,但我还是想不通怎么做. (2认同)

Noo*_*ass 11

你实际上可以有一个正确的方法.这是一个可以让你有代码CGPointRawValueenum:

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"
Run Code Online (Sandbox Code Playgroud)