Swift Lazy和Optional属性
Swift中的Lazy
或Optional
属性有什么区别?
例如,如果有人正在构建从侧面进来的导航栏,我认为应该都在一个UIViewController
。 用户可能永远不会打开菜单,但有时他们会打开。
var menu: NavigationBar? lazy var menu: NavigationBar = NavigationBar.initialize()
我认为这两个选项都是很好的代码,因为除非需要,否则它们不会创建视图。 我理解Optional
意味着可能有一个值可能是nil
。 我也理解Lazy
意味着在我需要它之前不要担心它。
具体问题
我的问题是他们的表现模式(安全和速度),说选项更快更安全,反之亦然?
好的,这是一个有趣的问题,我不想暗示现有的答案不好,但我想我会提出我的看法。
lazy
变量非常适合需要设置一次的东西,然后永远不会重新设置。 它是一个变量,因此您可以将其更改为其他内容,但这种方法会破坏lazy
变量的目的(即根据需要设置自己)。
对于可能消失的东西(可能会再次出现),可选项更多。 他们每次都需要设置。
因此,让我们看一下侧边菜单的两种情况:一种是在不可见时保持在周围的情况,另一种是在解除分配时。
lazy var sideMenu = SideMenu()
因此,第一次访问sideMenu
属性时,将调用SideMenu()
并将其分配给属性。 即使你没有使用它,实例也会永远存在。
现在让我们看看另一种方法。
var _sideMenu: SideMenu? var sideMenu: SideMenu! { get { if let sm = _sideMenu { return sm } else { let sm = SideMenu() _sideMenu = sm return sm } } set(newValue) { _sideMenu = newValue } }
(注意这只适用于类,而不适用于结构。)
好的,这是做什么的? 好吧,它的行为与lazy
var非常相似,但它让你重新设置为nil
。 因此,如果您尝试访问sideMenu
,则可以保证获得一个实例(存储在_sideMenu
中的_sideMenu
或新实例)。 这是一个类似的模式,它懒惰地加载SideMenu()
但是这个可以创建许多SideMenu()
实例,前面的例子只能创建一次。
现在,大多数视图控制器都足够小,你可能只是使用之前的lazy
。
因此,针对同一问题的两种不同方法。 两者都有利有弊,在不同情况下工作更好或更差。
他们实际上是非常不同的。
Optional
意味着该值可能为零,并且用户不保证它不会。 在您的示例中, var menu: NavigationBar?
除非有明确指定的内容,否则在整个课程的生命周期内都可能为零。
另一方面, Lazy
意味着在第一次访问赋值时不会调用赋值,这意味着代码中的某个地方有人试图使用您的对象。 但是请注意,如果你声明它就像你在这里lazy var menu: NavigationBar = NavigationBar.initialize()
那样STILL承诺不是nil lazy var menu: NavigationBar = NavigationBar.initialize()
,所以不需要做可选的链接。
实际上,变量可以是BOTH Lazy
AND Optional
,这意味着它的值将在首次访问时加载,并且该值在初始化时或任何未来点可能为nil。 例如:
lazy var menu: NavigationBar? = NavigationBar.initialize()
现在允许NavigationBar.initialize()
返回nil,或者将来某人可以将menu
设置为nil,而不会导致编译器/运行时抛出错误!
这有什么区别吗?
编辑:至于哪个更好,这是一个案例的事情。 Lazy
变量在第一次初始化时会受到性能影响,因此如果初始化过程很长,第一次访问将是一个缓慢的访问。 否则,它们在安全性/性能方面几乎相同。 在使用之前你需要解开的Optional
变量,所以这是一个非常小的性能成本(一台机器指令,不值得考虑时间)
可选和惰性属性不一样
- 当有可能值不可用时(即可以为nil),使用可选属性。 但在您的方案中,导航栏将始终可用,只是用户可能无法打开它。
- 因此,使用懒惰的物业符合您的目的。 只有当用户点击它时,才会初始化NavigationBar。
我没有看到任何性能问题,除非你使用一个可选项,在访问它之前每次检查值是否为nil还有额外的开销。