回到 2016 年 11 月,我发布了一个问题,询问为什么我不能使用 guard 创建一个使用与可选变量相同名称的变量的未包装版本,就像你可以使用 if let 一样:
链接: Why isn't guard let foo = foo valid?
当我写这个问题时,下面的代码将无法编译并出现“定义与先前值冲突”的错误:
//Test of using guard to create an unwrapped version of a var, like if let
func guardTest(_ viewController: UIViewController?) -> UIViewController? {
// Check if the current viewController exists
print(String(describing: viewController))
guard let viewController = viewController else {
return nil
}
print(String(describing: viewController))
return viewController
}
但是,我只是在工作中发现了一些执行此操作的代码,现在它可以毫无怨言地编译并执行我想要它执行的操作!运行时,打印语句显示 foo 是守卫之前的可选,之后是未包装的可选:
viewController = Optional(<TrochoidDemo.ViewController: 0x7ff16a039a00>)
viewController = <TrochoidDemo.ViewController: 0x7ff16a039a00>
(如果您想尝试一下,我将测试函数 guardTest(_:)
添加到了我最新的开源项目中。它可以在 Github 上找到 https://github.com/DuncanMC/TrochoidDemo )
我很高兴这个构造现在可以按照我想要的方式运行,但对为什么它现在是合法的以及何时发生变化感到困惑。
是否有人知道最近对语言定义的更改使得此构造在以前无法工作的地方工作?
最佳答案
长话短说
guard let foo = foo
是合法的,如果 foo
是在另一个范围内定义的。
您的链接问题中的示例:
func test()
{
let a: Int? = 1
guard let a = a else{
return
}
print("a = \(a)")
}
仍然不起作用,因为 guard
语句试图在同一范围内创建另一个变量 a
。
这个例子:
//Test of using guard to create an unwrapped version of a var, like if let
func guardTest(_ viewController: UIViewController?) -> UIViewController? {
// Check if the current viewController exists
print(String(describing: viewController))
guard let viewController = viewController else {
return nil
}
print(String(describing: viewController))
return viewController
}
工作原理与此相同:
func test(a: Int)
{
print(type(of: a)) // Int
let a = 3.14
print(type(of: a)) // Double
}
函数的参数在不同的范围内定义,因此 Swift 允许您创建一个具有相同名称的局部变量。
关于swift - `guard let foo = foo` 什么时候合法的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41854162/