Swift中的懒加载

Posted 程序猿说

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Swift中的懒加载相关的知识,希望对你有一定的参考价值。

1. lazy

class NetworkManager {
    lazy var urlSession: URLSession = {
        let configuration = URLSessionConfiguration.default
        let urlSession = URLSession(configuration: configuration)
        return urlSession
    }()
}

lazy 为 Swift 中的关键字,可以用于类和结构体的存储变量属性,表示该属性只在首次进行访问时初始值才会计算和存储。

需要注意的是:


If a property marked with the lazy modifier is accessed by multiple threads simultaneously and the property has not yet been initialized, there is no guarantee that the property will be initialized only once. 如果标记有 lazy 修饰符的属性同时被多个线程访问,并且该属性尚未初始化,则不能保证该属性仅被初始化一次。

import Foundation

class LazyPropertyClass {
    lazy var value: Int = {
        return Int.random(in0...100)
    }()
}

let instance = LazyPropertyClass()

for i in 0...3 {
    DispatchQueue(label: "\(i)", attributes: .concurrent).async {
        print(instance.value)
    }
}
// 47
// 53
// 67
// 67

2. 全局属性

struct ViewConstants {
    static let padding: CGFloat = 12.0
    static let toolbarHeight: CGFloat = 56.0
}

全局变量是定义在任何函数、方法、闭包之外或者其他类型上下文的变量。局部变量是定义在函数、方法之内或者闭包上下文的变量

在 https://docs.swift.org/swift-book/LanguageGuide/Properties.html#ID263 有下面一段话。

Global constants and variables are always computed lazily, in a similar manner to Lazy Stored Properties. Unlike lazy stored properties, global constants and variables do not need to be marked with the lazy modifier. 全局常量和变量总是延迟计算,与惰性存储属性类似的方式。与惰性存储的属性不同的是,全局常量和变量不需要使用 lazy 修饰符进行标记。

Local constants and variables are never computed lazily. 局部常量和变量永远不会延迟计算。

import Foundation

let value1: Int = {
    print("load value1")
    return Int.random(in0...100)
}()

class GlobalAndLocalPropertyClass {

    static let value2: Int = {
        print("load value2")
        return Int.random(in0...100)
    }()
    
    static var value3: Int = {
        print("load value3")
        return Int.random(in0...100)
    }()
    
    lazy var value4: Int = {
        print("load value4")
        return Int.random(in0...100)
    }()
    
    let value5: Int = {
        print("load value5")
        return Int.random(in0...100)
    }()
    
    var value6: Int = {
        print("load value6")
        return Int.random(in0...100)
    }()
}

// 初始化 GlobalAndLocalPropertyClass
// _ = GlobalAndLocalPropertyClass()

// 运行打印:
// load value5
// load value6

注意,在 Playground 中执行:

// load value1
// load value5
// load value6

3. LazySequenceProtocol

let doubled = [123].lazy.map { $0 * 2 }
print(doubled)
  • LazyCollectionProtocol 继承 LazySequenceProtocol协议
  • Lazy 表示延迟执行
  • Sequence: 一种类型,提供对元素的顺序和迭代访问
  • Collection: 一个序列,元素可以无损地遍历多次,并由索引下标访问
  • 避免不必要的存储分配和计算。

符合 LazySequenceProtocol 的类型

  • LazySequence
  • LazyMapSequence
  • LazyDropWhileSequence
  • LazyFilterSequence
  • LazyPrefixWhileSequence
  • ReversedCollection

当且仅当 Base 符合 LazySequenceProtocol 时才符合

  • Slice

当且仅当 Base 符合 LazySequenceProtocol 时才符合

  • LazyCollection
typealias LazyCollection<T> = LazySequence<Twhere T : Collection
  • LazyMapCollection
typealias LazyMapCollection<TU> = LazyMapSequence<TUwhere T : Collection
  • LazyDropWhileCollection
typealias LazyDropWhileCollection<T> = LazyDropWhileSequence<Twhere T : Collection
  • LazyFilterCollection
typealias LazyFilterCollection<T> = LazyFilterSequence<Twhere T : Collection
  • LazyPrefixWhileCollection
typealias LazyPrefixWhileCollection<T> = LazyPrefixWhileSequence<Twhere T : Collection

使用

// Array 有一个lazy属性返回类型为LazySequence<Array<Element>> 
let arr = [12 ,3]

let ls = arr.lazy
print(type(of: ls)
// LazySequence<Array<Int>>

let doubled = ls.map { $02 }
print(type(of: doubled))
// LazyMapSequence<Array<Int>, Int>

let greaterThanOne = ls.filter { $0 > 1 }
print(type(of: greaterThanOne))
// LazyFilterSequence<Array<Int>>

let lessThanTwo = ls.lazy.drop { $0 < 2 }
print(type(of: lessThanTwo))
// LazyDropWhileSequence<Array<Int>>

let lessonThanThree = ls.lazy.prefix { $0 < 3 }
// LazyPrefixWhileSequence<Array<Int>>

参考

  • https://docs.swift.org/swift-book/LanguageGuide/Properties.html

  • https://developer.apple.com/documentation/swift/lazysequenceprotocol


以上是关于Swift中的懒加载的主要内容,如果未能解决你的问题,请参考以下文章

Swift中的懒加载

Swift 懒加载

mybatis中的懒加载

swift 之 纯代码创建 cell

解决hibernate中的懒加载(延迟加载)问题

图片网站中的懒加载和预加载(转)