Swift - Lazy Var vs.以编程方式创建视图(保存内存)

时间:2017-11-18 15:02:13

标签: swift var let

我是初学者,我有点理解Lazy Var vs. Let。我注意到,当使用Lazy Var时,特别是使用ImageViews,可以节省大量的内存使用量。但是到目前为止我看过的教程和指南并没有经常使用Lazy Var,所以我很怀疑这是不好的做法而且我忽略了一些东西。

我做了一些研究,并了解到Lazy不是“线程安全”,但我不明白这意味着什么。我已经看到了很多优点和缺点,但我无法得出任何结论,特别是因为我的知识非常有限。

在创建UIView时,何时可以(或更好)使用Lazy Var vs. Let?

lazy var profileImageView: UIImageView = {

    let imageView = UIImageView(image: #imageLiteral(resourceName: "page1"))
    imageView.translatesAutoresizingMaskIntoConstraints = false
    imageView.contentMode = .scaleAspectFit
    return imageView

}()

3 个答案:

答案 0 :(得分:3)

是否使用lazy var取决于您的代码及其上下文。它本身并不坏或好。你必须决定什么时候合适。

在您决定之前,您必须知道lazy var是什么。

什么是lazy var

延迟初始化是一种概念,其中可变内容的初始化(构造)被延迟到第一次使用。首次访问此类变量会触发初始化。由于在使用(需要)变量之前不会创建内容,因此使用惰性初始化变量可以节省资源。

这是延迟初始化的主要驱动力。在您需要之前,您不会创造任何东西。这也是您在决定某事物是否应该lazy var时使用的逻辑。

如果您正在处理始终可见(需要)的视图(或其他任何内容),则使用延迟初始化几乎没有意义。另一方面,当您处理并非总是需要的实例时 - 使用lazy var是合理的。

如果您的视图在呈现的视图控制器中始终可见,则通过使其变得懒惰将无法实现。如果它仅在特定情况下可见 - 例如当用户展开某些折叠面板时 - 那么使其变得懒惰是有道理的。它会使您的视图控制器加载更快,默认情况下使用更少的内存。

就线程安全而言,lazy var在Swift中不是线程安全的。

这意味着如果两个不同的线程同时尝试访问相同的lazy var,则在初始化此变量之前,其中一个线程可能会访问部分构造的实例。

您可以在以下位置找到有关线程安全的更多信息:

Swift - is lazy var thread-safe?

Make "lazy var" threadsafe

答案 1 :(得分:3)

使用lazy var的另一个好处是提高了代码的可读性。

在您的示例中,与图像视图相关的代码被分组在一起,而不是分散到初始化程序,设置功能或viewDidLoad。这样可以通过不要求代码的读者冒险到代码中的各个位置来理解视图的配置来改进本地推理。要了解您的观点,他们只需要跳到其声明。

标记为lazy var的初始化闭包可以访问self,允许在闭包内部进行更多配置,例如添加目标操作或引用其他常量属性。

我会考虑使用闭包初始化属性(尤其是视图)lazy var是一个很好的做法,而且它似乎也在Swift社区中越来越受欢迎。

根据项目的不同,节省开发人员的时间比保存系统内存更有价值。

答案 2 :(得分:0)

使用惰性变量可以解决一个自相矛盾的问题:您要创建一个包含子视图的自定义视图,该子视图的初始化引用父视图。

例如,如果要创建包含相同大小的子UIScrollView的UIView子类,则不能声明包含以下内容的类:

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)