swift 中的 Lazy

作者: jianshudxw | 来源:发表于2019-02-21 14:35 被阅读0次

前言

lazy,延迟加载,以前只知道延迟属性,这个和 OC 中很多时候重写 getter 方法类似,只是今天看到 self.lazy.map 这样的用法,初次见面,多多学习。

主要有两种情况:

  1. lazy 修饰符,lazy属性
  2. lazy 方法, 集合的一个方法

lazy 修饰符

lazy属性就是初始值直到第一次使用的时候才执行计算的属性
注意:lazy属性必须是变量(var修饰符),因为常量属性(let修饰符)必须在初始化之前就有值,所以常量属性不能定义为lazy

Objective-C中的延迟加载

Objective-C并没有在语法上支持延迟加载,通常是由程序员自己手动实现的。
示例如下:

@property (nonatomic, strong) NSArray *names;

- (NSArray *)names {
    if (!_names) {
        _names = [[NSArray alloc] init];
        NSLog(@"只在首次访问输出");
    }
    return _names;
}

说明:在初始化对象后,_names 是 nil。只有当首次访问 names 属性时 getter 方法会被调用,并检查如果还没有初始化的话,就进行赋值。可以想见,控制台打印的“只在首次访问输出”的确只会输出一次。我们之后再多次访问这个属性的话,因为 _names已经有值,因此将直接返回。

分析:getter方法和下划线语法对初学者并不是那么的友好,同时属性以及对应的getter方法空间上隔得比较远,代码逻辑不直观。

Swift的延迟加载

Swift中则可以通过lazy关键字简单地实现相同功能,比如上述示例代码在Swift中实现的话:

lazy var names: NSArray = {
    let names = NSArray()
    print("只在首次访问输出")
    return names
}()

分析:相比起Objective-C中的实现,现在的lazy是在是简单的多了,而且更加的直观。除了上述直接在属性后面定义闭包调用的方法以外,还可以使用实例方法(func)和类方法(class func)来为lazy属性初始化添加必要的逻辑。

为了简化,我们如果不需要做什么额外工作的话,也可以对这个 lazy 的属性直接写赋值语句:

lazy var str: String = "Hello"

使用场景

延迟加载主要有以下两个使用的场景:

  1. 属性的初始值依赖于其他的属性值,只有其他的属性值有值之后才能得出该属性的值。
  2. 属性的初始值需要大量的计算。

lazy 方法

标准库中定义:


/// Augment `self` with lazy methods such as `map`, `filter`, etc.
extension Collection {

    /// A view onto this collection that provides lazy implementations of
    /// normally eager operations, such as `map` and `filter`.
    ///
    /// Use the `lazy` property when chaining operations to prevent
    /// intermediate operations from allocating storage, or when you only
    /// need a part of the final collection to avoid unnecessary computation.
    public var lazy: LazyCollection<Self> { get }
}
func lazy<S : SequenceType>(s: S) -> LazySequence<S>

func lazy<S : CollectionType where S.Index : RandomAccessIndexType>(s: S)
                -> LazyRandomAccessCollection<S>

func lazy<S : CollectionType where S.Index : BidirectionalIndexType>(s: S)
                -> LazyBidirectionalCollection<S>

func lazy<S : CollectionType where S.Index : ForwardIndexType>(s: S)
                -> LazyForwardCollection<S>

这些方法可以配合像 map 或是 filter 这类接受闭包并进行运行的方法一起,让整个行为变成延时进行的。在某些情况下这么做也对性能会有不小的帮助。例如,直接使用 map 时:

let data = 1...3
let result = data.map {
    (i: Int) -> Int in
    print("正在处理 \(i)")
    return i * 2
}

print("准备访问结果")
for i in result {
    print("操作后结果为 \(i)")
}

print("操作完毕")

这么做的输出为:

// 正在处理 1
// 正在处理 2
// 正在处理 3
// 准备访问结果
// 操作后结果为 2
// 操作后结果为 4
// 操作后结果为 6
// 操作完毕

而如果我们先进行一次 lazy 操作的话,我们就能得到延时运行版本的容器:

let data = 1...3
let result = data.lazy.map {
    (i: Int) -> Int in
    print("正在处理 \(i)")
    return i * 2
}

print("准备访问结果")
for i in result {
    print("操作后结果为 \(i)")
}

print("操作完毕")

// 准备访问结果
// 正在处理 1
// 操作后结果为 2
// 正在处理 2
// 操作后结果为 4
// 正在处理 3
// 操作后结果为 6
// 操作完毕

参考

LAZY 修饰符和 LAZY 方法
Swift的lazy关键字–延迟加载
Swift Collection 中的 lazy 作用

相关文章

  • swift 中的 lazy

    概念 延迟加载是初始化很常用的性能优化方式,尤其是在一些对象的属性十分复杂的时候,默认全部初始化会耗费不少时间,影...

  • swift 中的 Lazy

    前言 lazy,延迟加载,以前只知道延迟属性,这个和 OC 中很多时候重写 getter 方法类似,只是今天看到 ...

  • Swift总结4:UI控件 单例 代理 懒加载 网络请求 闭包

    //懒加载//swift中固定写法lazy var l:UILabel = { //viewDidLoad中vie...

  • swift 中 Lazy,deinit用法

    * swift中懒加载写法,懒加载在Swift中是一个闭包。 懒加载详细介绍看这里 * OC中的dealloc方法...

  • Swift Collection 中的 lazy 作用

    惰性求值 惰性求值常见于函数式编程中,也有人把惰性求值翻译成延迟求值(Lazy Evaluation)。它的目的是...

  • Framework: lazy symbol bind fail

    Framework: lazy symbol bind failed 解决记录 XCode Swift 兼容问题 ...

  • Swift中懒加载

    在Swift中对控件进行懒加载比oc中方便很多,只要lazy前缀,oc中懒加载方法,重写getter方法.Swif...

  • Swift里的lazy

    惰性初始化,就是在变量第一次使用的时候才进行初始化。 Swift中,有两种方式来惰性初始化。 第一种,简单表达式 ...

  • swift —— tips swift 中的懒加载实现

    objc objc 对象的懒加载 swift swift 的懒加载 方式 1lazy 保证数据在用到的时候才会被加...

  • Swift:)懒加载Lazy

    OC中,要实现懒加载是用到getter方法,例如 Swift懒加载差别就很大了,懒加载属性用lazy修饰,注意结尾...

网友评论

    本文标题:swift 中的 Lazy

    本文链接:https://www.haomeiwen.com/subject/mtpryqtx.html