早在2016年11月,我发布了一个问题,询问为什么我不能使用Guard创建与变量名称相同的未包装版本的变量,就像让let那样:
链接: 为什么后卫不让foo = foo有效?
当我编写该问题时,以下代码将无法编译,并显示“定义与先前值冲突”的错误:
//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 }
但是,我只是在工作中发现了一些可以做到这一点的代码,现在它可以毫无抱怨地进行编译,并且可以完成我想要的工作!运行时,print语句显示foo在警卫之前是可选的,而在包装后是未包装的可选的:
viewController = Optional(<TrochoidDemo.ViewController: 0x7ff16a039a00>) viewController = <TrochoidDemo.ViewController: 0x7ff16a039a00>
(guardTest(_:)如果您想尝试一下,我将测试功能添加到了最新的开源项目中。可以在Github上的 https://github.com/DuncanMC/TrochoidDemo上找到该功能 )
guardTest(_:)
我很高兴这个构造现在可以按我希望的方式工作,但是对于 为什么 现在合法以及更改发生的时间感到困惑。
是否有人知道对语言定义的最新更改,使此构造在以前从未有过的地方起作用?
TL; DR
guard let foo = foo如果foo在其他范围内定义,则为合法。
guard let foo = foo
foo
您的链接问题中的示例:
func test() { let a: Int? = 1 guard let a = a else{ return } print("a = \(a)") }
仍然不起作用,因为该guard语句试图a在相同范围内创建另一个变量。
guard
a
这个例子:
可以这样做的原因相同:
func test(a: Int) { print(type(of: a)) // Int let a = 3.14 print(type(of: a)) // Double }
该函数的参数在不同的范围内定义,因此Swift允许您创建具有相同名称的局部变量。