Swift 延迟和可选属性
Swift Lazy and Optional properties
Swift中的Lazy
或Optional
属性有什么区别?
例如,如果有人正在构建一个从侧面进入的导航栏,我认为应该都在一个内UIViewController
。用户可能永远不会打开菜单,但有时他们会打开。
var menu: NavigationBar?
lazy var menu: NavigationBar = NavigationBar.initialize()
我认为这两个可选代码都是很好的代码,因为除非需要,否则它们不会创建视图。我理解 Optional
意味着可能有一个值可能是 nil
。我也理解 Lazy
意味着在我需要它之前不要担心它。
具体问题
我的问题是,他们的性能模式(安全性和速度)是否表明可选项更快更安全,或者反之亦然?
它们实际上非常不同。
Optional
表示该值可能为零,用户不保证它不会。在您的示例中,var menu: NavigationBar?
在 class 的整个生命周期内可能为 nil,除非明确指定它。
另一方面,Lazy
意味着在首次访问之前不会调用赋值,这意味着代码中某处有人试图使用您的对象。但是请注意,如果您像此处那样声明它,它仍然承诺不会为 nil lazy var menu: NavigationBar = NavigationBar.initialize()
,因此无需进行可选链接。
实际上,一个变量可以是 Lazy
和 Optional
,这意味着它的值将在首次访问时加载,并且该值在初始化时可能为 nil或在未来的任何时候。例如:
lazy var menu: NavigationBar? = NavigationBar.initialize()
现在允许 NavigationBar.initialize()
为 return nil,或者将来有人可以将 menu
设置为 nil 而不会 compiler/runtime 抛出错误!
这样区分清楚了吗?
编辑:
至于哪个更好,那要视具体情况而定。 Lazy
变量在第一次初始化时会影响性能,因此如果初始化过程很长,第一次访问将会很慢。否则,它们在 safety/performance 方面几乎相同。 Optional
变量在使用前必须解包,因此性能成本非常小(一条机器指令,不值得花时间考虑)
可选属性和惰性属性不一样
- 当值可能不可用(即可以为零)时,使用可选的 属性。但是在您的场景中,导航栏将始终可用,只是用户可能不会打开它。
- 所以使用惰性 属性 可以达到你的目的。 NavigationBar 只有在用户点击它时才会被初始化。
我没有看到任何性能问题,除了如果你使用一个可选的,每次访问它之前检查值是否为 nil 都会有额外的开销。
好的,这是一个有趣的问题,我不想暗示现有的答案不好,但我想我会提供我对事情的看法。
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()
个实例,而前面的示例只能创建一次。
现在,大多数视图控制器都足够小,您可能应该只使用之前的 lazy
。
所以对同一个问题有两种不同的方法。两者都有优点和缺点,并且在不同情况下效果更好或更差。
Swift中的Lazy
或Optional
属性有什么区别?
例如,如果有人正在构建一个从侧面进入的导航栏,我认为应该都在一个内UIViewController
。用户可能永远不会打开菜单,但有时他们会打开。
var menu: NavigationBar?
lazy var menu: NavigationBar = NavigationBar.initialize()
我认为这两个可选代码都是很好的代码,因为除非需要,否则它们不会创建视图。我理解 Optional
意味着可能有一个值可能是 nil
。我也理解 Lazy
意味着在我需要它之前不要担心它。
具体问题
我的问题是,他们的性能模式(安全性和速度)是否表明可选项更快更安全,或者反之亦然?
它们实际上非常不同。
Optional
表示该值可能为零,用户不保证它不会。在您的示例中,var menu: NavigationBar?
在 class 的整个生命周期内可能为 nil,除非明确指定它。
Lazy
意味着在首次访问之前不会调用赋值,这意味着代码中某处有人试图使用您的对象。但是请注意,如果您像此处那样声明它,它仍然承诺不会为 nil lazy var menu: NavigationBar = NavigationBar.initialize()
,因此无需进行可选链接。
实际上,一个变量可以是 Lazy
和 Optional
,这意味着它的值将在首次访问时加载,并且该值在初始化时可能为 nil或在未来的任何时候。例如:
lazy var menu: NavigationBar? = NavigationBar.initialize()
现在允许 NavigationBar.initialize()
为 return nil,或者将来有人可以将 menu
设置为 nil 而不会 compiler/runtime 抛出错误!
这样区分清楚了吗?
编辑:
至于哪个更好,那要视具体情况而定。 Lazy
变量在第一次初始化时会影响性能,因此如果初始化过程很长,第一次访问将会很慢。否则,它们在 safety/performance 方面几乎相同。 Optional
变量在使用前必须解包,因此性能成本非常小(一条机器指令,不值得花时间考虑)
可选属性和惰性属性不一样
- 当值可能不可用(即可以为零)时,使用可选的 属性。但是在您的场景中,导航栏将始终可用,只是用户可能不会打开它。
- 所以使用惰性 属性 可以达到你的目的。 NavigationBar 只有在用户点击它时才会被初始化。
我没有看到任何性能问题,除了如果你使用一个可选的,每次访问它之前检查值是否为 nil 都会有额外的开销。
好的,这是一个有趣的问题,我不想暗示现有的答案不好,但我想我会提供我对事情的看法。
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()
个实例,而前面的示例只能创建一次。
现在,大多数视图控制器都足够小,您可能应该只使用之前的 lazy
。
所以对同一个问题有两种不同的方法。两者都有优点和缺点,并且在不同情况下效果更好或更差。