Swift 编译器在 switch 语句上崩溃,需要解决方法

Swift compiler crashes on switch statement, need workaround

我得到的代码基本上是这样的,尽管我不确定这个提炼版本是否完全重现了编译器崩溃:

enum Response<T> {
    case Success(T)
    case Failure(String)
}

struct ResponseData {
    let someData = "some data"
}

func evaluate() {
    let response = Response.Success(ResponseData())

    switch response {
    case let .Success(data):
        println("Got response with \(data)")
    case let .Failure(reason):
        println("Got failure: \(reason)")
    default: ()
    }
}

Xcode 编辑器没有检测到任何问题,但是当我构建时,编译器崩溃并出现以下错误:

Command /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/swiftc failed with exit code 1

当我注释掉 .Success 案例时,我可以正常构建。我猜 Swift 编译器不喜欢泛型作为与枚举的关联值。但是,该模式对我来说非常有用,它使代码更具可读性。知道我该如何解决这个问题吗?据我所知,除了使用 switch 语句之外,没有其他方法可以访问关联值。

我还应该提一下,我已经找到了 the question here,但没有充分利用所提供的解决方案。

编辑 实际上下面已经抛出了段错误:

enum Response<T> {
    case Success(T)
    case Failure(String)
}

struct ResponseData {
    let someData = "some data"
}

func evaluate() {
    let response = Response.Success(ResponseData())
}

unimplemented IR generation feature non-fixed multi-payload enum layout enum Response {

解决方案真正归功于上面发表评论的每个人。

问题似乎是 Swift 编译器想知道枚举在内存中的确切大小。泛型使这成为不可能,因此编译器无法正确运行。

我采用的解决方案取自 Rob Rix 的库,该库是将泛型封装在另一种类型中。请注意,它必须是 class,因为引用具有已知大小,但具有泛型的结构却没有。

@autoclosure 解决方案似乎也很有趣,但它不适用于最新版本的 Xcode。这是设计使然;据我了解,开发人员不希望每次计算枚举时都关闭 运行。

谢谢大家!

看起来您只能使用从 NSObject 继承的对象

像这样

enum Result<T: NSObject>: Printable {
    case Success(T)
    case Error(NSError)

    var description: String {
        switch self{
        case .Success(let obj):
            return obj.description
        case .Error(let error):
            return error.description
    }
}

然后

let r = Result.Success("Xcode")

r.description

更新: 你可以这样做

@objc
protocol ResultObjectProtocol {
    var description: String { get }
}

extension NSDictionary: ResultObjectProtocol {}

enum Result<T: ResultObjectProtocol>: Printable {
    case Success(T)
    case Failure(NSError)

    var description: String {
        switch self{
        case .Success(let obj):
            return obj.description
        case .Failure(let error):
            return error.description
        }
    }
}

let r = Result.Success(["d" : 132]).description

注:var description - 仅供参考

更新。 (Swift 4) 您可以在枚举中自由使用泛型类型:

enum Result<T> {
    case success(T)
    case error(Error)
}