Ios Swift属性和可选属性

Ios Swift属性和可选属性,ios,swift,uikit,optional,lazy-initialization,Ios,Swift,Uikit,Optional,Lazy Initialization,Swift中的惰性或可选属性之间有什么区别 例如,如果有人正在构建一个从侧面进入的导航栏,我认为所有导航栏都应该位于一个UIViewController中。用户可能永远不会打开菜单,但有时会打开 var menu: NavigationBar? lazy var menu: NavigationBar = NavigationBar.initialize() 我认为这两个可选代码都是很好的代码,因为除非需要,否则它们不会创建视图。我理解Optional意味着可能存在一个值,它可能是nil。我也

Swift中的
惰性
可选
属性之间有什么区别

例如,如果有人正在构建一个从侧面进入的导航栏,我认为所有导航栏都应该位于一个
UIViewController
中。用户可能永远不会打开菜单,但有时会打开

var menu: NavigationBar?
lazy var menu: NavigationBar = NavigationBar.initialize()
我认为这两个可选代码都是很好的代码,因为除非需要,否则它们不会创建视图。我理解
Optional
意味着可能存在一个值,它可能是
nil
。我也明白懒惰意味着在我需要它之前不要担心它

具体问题


我的问题是,他们的性能模式(安全和速度)是说可选的更快、更安全,还是相反

它们其实很不一样

Optional
表示该值可能为零,用户不能保证它不会为零。在您的示例中,
var-menu:NavigationBar?
在类的整个生命周期中可能为零,除非有东西显式分配它

另一方面,
Lazy
意味着在首次访问分配之前不会调用它,这意味着代码中的某个地方有人试图使用您的对象。但是请注意,如果您像在这里一样声明它,它仍然承诺不会为零
lazy var menu:NavigationBar=NavigationBar.initialize()
,因此无需执行可选链接

实际上,一个变量既可以是
惰性的
也可以是
可选的
,这意味着它的值将在第一次访问时加载,并且在初始化时或将来的任何时候,该值可能为零。例如:

lazy var menu: NavigationBar? = NavigationBar.initialize()
现在允许
NavigationBar.initialize()
返回nil,或者将来有人可以将
菜单设置为nil,而不会引发编译器/运行时错误

这就清楚了区别吗

编辑:
至于哪一个更好,这实际上是一个个案的事情<代码>惰性
变量在第一次初始化时会受到性能影响,因此,如果初始化过程很长,那么第一次访问将是缓慢的。否则,它们在安全性/性能方面几乎相同<代码>可选的在使用之前必须展开的变量,因此它的性能成本很小(一条机器指令,不值得花时间考虑)

可选和惰性属性不一样

  • 当值可能不可用时(即可以为nil),将使用可选属性。但在您的场景中,导航栏始终可用,只是用户可能无法打开它
  • 因此,使用惰性属性符合您的目的。导航栏只有在用户点击时才会初始化

我看不到任何性能问题,除了如果使用一个可选的,那么在每次访问它之前检查该值是否为零会增加额外的开销

好吧,这是一个有趣的问题,我不想暗示现有的答案不好,但我想我会给出我的看法

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
。因此,如果您尝试访问
侧菜单
,您一定会得到一个实例(存储在
\u侧菜单
中的实例或一个新实例)。这是一个类似的模式,它延迟加载
SideMenu()
,但是这个可以创建许多
SideMenu()
实例,前面的示例只能创建一个实例

现在,大多数视图控制器都足够小,您可能只需要使用前面提到的
lazy


所以对同一个问题有两种不同的方法。两者都有优点和缺点,在不同的情况下效果更好或更差

只是一个问题-如果您加载了NavigationBar(视图)延迟,您如何将其添加到父视图并设置其在viewDidLoad上发生的属性?我见过惰性加载对初始化或计算密集型属性不需要的对象属性做了更多的处理。长回答短-使用带有“targetAction”的按钮,然后在action just self.view.addSubview(菜单)中打开。在我看来,导航栏的设置几乎总是一样的。明白了。因此,菜单不在屏幕上,但只有当用户与该按钮交互时,才需要运行加载它所需的代码。基本上是的。您可以添加滑动手势或任何想要显示菜单的动作。我刚刚举了一个例子,我的问题更多的是关于安全性和速度性能。我认为懒惰和随意性是过分的。我的问题更多的是关于安全和性能。谢谢,我已经知道了。对不起,浪费了你的时间。我改进了我的问题,使我的问题更清楚。