Fyo*_*yok 4 error-handling closures syntax-error swift
在我的单元测试中,我有以下代码来检查抛出的错误是否是预期类型.它由两个相同的语句完成,其中一个语句不能编译:
enum Error: ErrorType {
case SomeExpectedError
case SomeUnexpectedError
}
func functionThatThrows() throws {
throw Error.SomeExpectedError
}
// 1) this compiles fine
XCTAssertThrowsError(try functionThatThrows()) { (error) in
switch error {
case Error.SomeExpectedError: break
//everything is fine
case Error.SomeUnexpectedError: fallthrough
default:
XCTFail("Unexpected error thrown")
}
}
// 2) doesn't compiles at all
XCTAssertThrowsError(try functionThatThrows()) { (error) in
XCTAssertEqual(error as? Error, Error.SomeExpectedError)
}
Run Code Online (Sandbox Code Playgroud)
第一个语句编译并正常工作,但第二个语句告诉我有两个错误:
Errors thrown from here are not handled和Cannot convert value of type '(Error) -> Void' to expected argument type 'String'.
这段代码有什么问题?错误消息是什么意思?
我正在使用Xcode 7.3.
经过一番研究后,我发现我的代码有两个问题:
1)似乎我的闭包被认为是"Impilictly return",因为它只包含一个可执行语句
2)编译器被我的语句搞糊涂了,因为XCTAssertThows接受了另一个接受闭包的参数 - 就是这样 @autoclosure _ message: () -> String
结果编译器认为我传递了消息的闭包(IMHO令人困惑的设计决策 - 传递@autoclosure作为消息参数),当我实际上传递了errorHandler的闭包.
解决方案很简单:
// explicitly show closure returning type Void so that compiler couldn't
// use it as message argument (which closure must return String)
XCTAssertThrowsError(try functionThatThrows()) { (error) -> Void in
XCTAssertEqual(error as? Error, Error.SomeExpectedError)
}
// explicitly show closure's argument type
XCTAssertThrowsError(try functionThatThrows()) { (error: ErrorType) in
XCTAssertEqual(error as? Error, Error.SomeExpectedError)
}
// use "message" parameter to preserve argument order
XCTAssertThrowsError(try functionThatThrows(), "some message") { (error) in
XCTAssertEqual(error as? Error, Error.SomeExpectedError)
}
// wrap executable line in "do {}". I guess it works because closure stops
// being "implicitly returning" and now compiler treat it as () -> Void
// which is expected type of errorHandler argument
XCTAssertThrowsError(try functionThatThrows()) { (error) in
do {
XCTAssertEqual(error as? Error, Error.SomeExpectedError)
}
}
Run Code Online (Sandbox Code Playgroud)