Swift - 以编程方式创建视图时的 Lazy Var 与 Let(节省内存)
Swift - Lazy Var vs. Let when creating views programmatically (saving memory)
我是初学者,我有点了解 Lazy Var 与 Let。我注意到在使用 Lazy Var 尤其是 ImageViews 时,它可以节省大量内存使用。但是到目前为止我看到的教程和指南并不经常使用 Lazy Var,所以我怀疑这是不好的做法并且我忽略了一些东西。
我做了一些调查,了解到 Lazy 不是 "thread safe,",但我不明白这是什么意思。我看过很多优缺点,但我不能得出任何结论,尤其是因为我的知识非常有限。
在创建 UIView 时,何时可以(或更好)使用 Lazy Var 与 Let?
lazy var profileImageView: UIImageView = {
let imageView = UIImageView(image: #imageLiteral(resourceName: "page1"))
imageView.translatesAutoresizingMaskIntoConstraints = false
imageView.contentMode = .scaleAspectFit
return imageView
}()
是否使用 lazy var
取决于您的代码及其上下文。它本身并不坏或好。你必须决定什么时候合适。
在你做出决定之前,你必须知道 lazy var
是什么。
什么是 lazy var
?
延迟初始化是一个概念,其中变量内容的初始化(构造)被延迟到第一次使用时。首次访问此类变量会触发初始化。由于在使用(需要)变量之前不会创建内容,因此使用惰性初始化变量可以节省资源。
这是惰性初始化背后的主要驱动力。除非你需要它,否则你不会创造它。这也是您在决定是否应 lazy var
时将使用的逻辑。
如果您正在处理始终可见(需要)的视图(或其他任何东西),那么使用惰性初始化毫无意义。另一方面,当您处理并不总是需要的实例时 - 那么使用 lazy var
是合理的。
如果您的视图在呈现的视图控制器中始终可见,那么通过使其惰性化您将无济于事。如果它只在特定情况下可见——例如当用户展开一些折叠的面板时——那么让它变得懒惰是有道理的。它将使您的视图控制器加载速度更快,默认情况下使用更少的内存。
就线程安全而言,lazy var
在 Swift 中不是线程安全的。
这意味着如果两个不同的线程试图同时访问同一个 lazy var
,在初始化此类变量之前,其中一个线程可能会访问部分构造的实例。
您可以在以下位置找到有关线程安全的更多信息:
使用 lazy var
的另一个好处是提高代码的可读性。
在您的示例中,与图像视图相关的代码组合在一起,而不是分散到初始化程序、设置函数或 viewDidLoad
。通过不需要代码的 reader 冒险到代码中的不同位置来了解您的视图是如何配置的,这改进了局部推理。要了解你的观点,他们只需要跳转到它的声明。
标记为 lazy var
的初始化闭包可以访问 self
,允许在闭包内进行更多配置,例如添加目标操作或引用其他常量属性。
我会考虑使用闭包初始化属性(尤其是视图)作为 lazy var
的一个好习惯,它似乎也在 Swift 社区中越来越受欢迎。
根据项目的不同,节省开发人员时间可能比节省系统内存更有价值。
惰性变量的使用可以解决一个矛盾的问题:您想创建一个自定义视图,其中包含子视图,其初始化引用父视图。
例如,如果您要创建包含相同大小的子 UIScrollView 的 UIView 的子class,则不能声明包含:
的 class
var m_scrollView: UIScrollView
override init(frame: CGRect)
{
m_scrollView = UIScrollView(frame: self.frame)
super.init(frame: frame)
}
编译器会抱怨您在调用 super.init 之前引用了 self。但是... super.init 必须在 所有成员初始化后 被调用。
这个循环问题的解决方案是使 m_scrollView 懒惰并在其声明中初始化它:
lazy var m_scrollView = UIScrollView(frame: self.frame)
我是初学者,我有点了解 Lazy Var 与 Let。我注意到在使用 Lazy Var 尤其是 ImageViews 时,它可以节省大量内存使用。但是到目前为止我看到的教程和指南并不经常使用 Lazy Var,所以我怀疑这是不好的做法并且我忽略了一些东西。
我做了一些调查,了解到 Lazy 不是 "thread safe,",但我不明白这是什么意思。我看过很多优缺点,但我不能得出任何结论,尤其是因为我的知识非常有限。
在创建 UIView 时,何时可以(或更好)使用 Lazy Var 与 Let?
lazy var profileImageView: UIImageView = {
let imageView = UIImageView(image: #imageLiteral(resourceName: "page1"))
imageView.translatesAutoresizingMaskIntoConstraints = false
imageView.contentMode = .scaleAspectFit
return imageView
}()
是否使用 lazy var
取决于您的代码及其上下文。它本身并不坏或好。你必须决定什么时候合适。
在你做出决定之前,你必须知道 lazy var
是什么。
什么是 lazy var
?
延迟初始化是一个概念,其中变量内容的初始化(构造)被延迟到第一次使用时。首次访问此类变量会触发初始化。由于在使用(需要)变量之前不会创建内容,因此使用惰性初始化变量可以节省资源。
这是惰性初始化背后的主要驱动力。除非你需要它,否则你不会创造它。这也是您在决定是否应 lazy var
时将使用的逻辑。
如果您正在处理始终可见(需要)的视图(或其他任何东西),那么使用惰性初始化毫无意义。另一方面,当您处理并不总是需要的实例时 - 那么使用 lazy var
是合理的。
如果您的视图在呈现的视图控制器中始终可见,那么通过使其惰性化您将无济于事。如果它只在特定情况下可见——例如当用户展开一些折叠的面板时——那么让它变得懒惰是有道理的。它将使您的视图控制器加载速度更快,默认情况下使用更少的内存。
就线程安全而言,lazy var
在 Swift 中不是线程安全的。
这意味着如果两个不同的线程试图同时访问同一个 lazy var
,在初始化此类变量之前,其中一个线程可能会访问部分构造的实例。
您可以在以下位置找到有关线程安全的更多信息:
使用 lazy var
的另一个好处是提高代码的可读性。
在您的示例中,与图像视图相关的代码组合在一起,而不是分散到初始化程序、设置函数或 viewDidLoad
。通过不需要代码的 reader 冒险到代码中的不同位置来了解您的视图是如何配置的,这改进了局部推理。要了解你的观点,他们只需要跳转到它的声明。
标记为 lazy var
的初始化闭包可以访问 self
,允许在闭包内进行更多配置,例如添加目标操作或引用其他常量属性。
我会考虑使用闭包初始化属性(尤其是视图)作为 lazy var
的一个好习惯,它似乎也在 Swift 社区中越来越受欢迎。
根据项目的不同,节省开发人员时间可能比节省系统内存更有价值。
惰性变量的使用可以解决一个矛盾的问题:您想创建一个自定义视图,其中包含子视图,其初始化引用父视图。
例如,如果您要创建包含相同大小的子 UIScrollView 的 UIView 的子class,则不能声明包含:
的 classvar m_scrollView: UIScrollView
override init(frame: CGRect)
{
m_scrollView = UIScrollView(frame: self.frame)
super.init(frame: frame)
}
编译器会抱怨您在调用 super.init 之前引用了 self。但是... super.init 必须在 所有成员初始化后 被调用。
这个循环问题的解决方案是使 m_scrollView 懒惰并在其声明中初始化它:
lazy var m_scrollView = UIScrollView(frame: self.frame)