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)
}
我得到的代码基本上是这样的,尽管我不确定这个提炼版本是否完全重现了编译器崩溃:
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)
}