【发布时间】:2015-10-19 01:13:50
【问题描述】:
我对一些使用 Xcode 7 beta 3 编译的 Swift 2 代码有疑问。
我有一个类(见下文),它有一个初始化器,它接受一个可以抛出的函数 f。如果 f 不抛出,则应将成员变量 (self.result) 设置为封装 f 返回值的枚举实例。如果 f 确实抛出,则 self.result 应设置为指示该值不存在的枚举实例。在初始化程序的末尾,self.result 不应为 nil。我已经检查了 f 不抛出的情况,并且行为是正确的。但是,在 f 确实抛出的情况下, self.result 在初始化程序的末尾是 nil (触发了断言)。如果我在调试器中单步执行,我会看到 self.result 似乎立即被设置,然后闪回为 nil。
(注意:您可能会建议我将没有结果表示为 nil,而不是包装在枚举中。但是,我需要对 f 的结果尚未计算但已成功计算的场景进行建模,或者尝试计算结果但失败了。因此是枚举。)
我是否误解了 Swift 2 的错误处理机制?或者,编译器/调试器等行为是否不正确?
提前致谢。
internal enum Result<T> {
case Value(T)
case None
}
public final class MyClass<T> {
internal var result: Result<T>? = nil
private init(f: () throws -> T) {
let queueName = “some.string”
let queue = dispatch_queue_create(queueName, DISPATCH_QUEUE_CONCURRENT)
dispatch_async(queue) {
do {
let value = try f()
self.result = .Value(value)
}
catch {
self.result = .None
}
assert(self.result != nil, "Result must have value before block returns.")
}
}
}
【问题讨论】:
-
克里斯,这是因为,控制将立即从 dispatch_async 中出来,甚至在调用 do..catch 之前,断言就被调用了。
-
@nshebbar:不,在调度块中,语句是按顺序执行的。
-
谢谢两位,但 Martin R 的回答是正确的。
-
哦,我应该更仔细地看一下!,我以为断言在异步块之外!