问题1:
guard let self = self else { return }
中,第一个self
和第二个self
是一样的,为什么可以编译成功?因为正常的let self = self
会编译出错。
问题2:即使我在某些项目中发现
guard let self else { return }
,为什么还能编译成功?
一些链接供您参考:
SE-0079讨论了
if let self = self {…}
模式的使用:
所提出的解决方案需要允许使用可选绑定将 self 从弱引用升级到强引用。
该提案取代了语法:
if let strongSelf = self { … }
使用一些避免引入单独变量名称的混乱的东西,将其减少为:
if let self = self { … }`
SE-0345中考虑了此语法的缩短,其中表示:
使用
进行可选绑定,创建一个隐藏现有可选变量的未包装变量,是一种极其常见的模式。此模式要求作者重复引用的标识符两次,这可能会导致这些可选绑定条件变得冗长,尤其是在使用冗长的变量名称时。当隐藏现有变量时,我们应该引入可选绑定的简写语法:if let foo = foo { ... }
let foo: Foo? = ... if let foo { // `foo` is of type `Foo` }
该模式也适用于自我,因此我第一点中的示例简化为:
if let self { … }`
FWIW,SE-0365,在“内隐自我”的讨论中,展示了许多
guard
模式的示例:
guard let self else {…}`
通过编写
let self = self
,您可以声明一个变量 self
并为其赋予值 self
(即,对该行在内部调用的对象实例的引用)。
Swift 允许变量遮蔽,因此创建一个局部变量
self
来遮蔽外部作用域中的标识符 self
是合法的。
但有一个警告:
self
在 Swift 中也是一个特殊的词,不能用作变量名(编译器会发出错误“关键字'self'不能在此处用作标识符”)...除非你应用转义技术:让 `self` = self.
另一方面,
guard
不需要这种转义。我想,由于习惯用法 guard let self = self
如此常见,语言开发人员决定破例,以避免一些样板代码。
在该语言的更高版本中,他们还引入了用于展开可选值的简写语法:
guard let self
。事实上,您可以将它与任何可选变量一起使用来打开它:guard let anyOptional
。
至于为什么
guard let self else { return }
在某些地方无法编译,没有更多细节就很难说,但我有两个假设:
self
本身可能在上下文中不可用(即代码是在对象实例之外编写的,例如在全局范围内)。