Swift Lazy和Optional属性

Swift中的LazyOptional属性有什么区别?

例如,如果有人正在构建从侧面进来的导航栏,我认为应该都在一个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还有额外的开销。