Lazy Initialization with Swift

Lazy initialization (also sometimes called lazy instantiation, or lazy loading) is a technique for delaying the creation of an object or some other expensive process until it’s needed. When programming for iOS, this is helpful to make sure you utilize only the memory you need when you need it.

This technique is so helpful, in fact, that Swift added direct support for it with the lazyattribute.

To understand why this is useful, let’s first go over the old way of creating lazy properties.


The Old Way

In Objective-C, if you had a mutable array property you wanted lazily initialized, you’d have to write this:

@property (nonatomic, strong) NSMutableArray *players;

- (NSMutableArray *)players {
    if (!_players) {
        _players = [[NSMutableArray alloc] init];
    }
    return _players;
}

To people new to Objective-C, this presents a few different learning curves. First of all, you need to know that the method name has to exactly match the property name. If you misspelled the method name, this would silently fail and players would be nil when you tried to access it.

You also need to know the _players instance variable was created for you automatically when your property was synthesized. Before Xcode 4.4, you had to manually synthesize your variable using the @synthesize keyword, like so:

@synthesize players;
// - or -
@synthesize players = _players;

Which would tell you that the instance variable used for the players property is _players. Nowadays Xcode handles synthesizing your properties for you. If you didn’t know that, then using the underscore before the property name might not be immediately obvious.


The Swift Way

Now in Swift, this can all be simplified down to one line:

lazy var players = [String]()

Simple, concise, and straight to the point.

Keep in mind you do need to declare your lazy property using the var keyword, not the letkeyword, because constants must always have a value before initialization completes.

If you wanted to add logic to your lazy initialization, Swift makes this easy by letting you define a closure after your lazy property:

lazy var players: [String] = {
        var temporaryPlayers = [String]()
        temporaryPlayers.append("John Doe")
        return temporaryPlayers
        }()

If you prefer, you can also lazily initiate your property using an instance method:

lazy var players: [String] = self.initialPlayers()

func initialPlayers() -> [String] {
    var players = ["John Doe"]
    return players
}

Or a class method:

class TestClass {
    lazy var players = TestClass.initialPlayers()

    class func initialPlayers() -> [String] {
        var players = ["John Doe"]
        return players
    }

}

But people will most likely prefer using the new closure mechanic, as it keeps the logic near the property declaration.


When should I use lazy initialization?

One example of when to use lazy initialization is when the initial value for a property is not known until after the object is initialized.

For example, if you have a Person class and a personalizedGreeting property. The personalizedGreeting property can be lazily instantiated after the object is created so it can contain the name of the person. Here’s a quick example:

class Person {

    var name: String

    lazy var personalizedGreeting: String = {
        [unowned self] in
        return "Hello, \(self.name)!"
        }()

    init(name: String) {
        self.name = name
    }
}

(Note that we had to say [unowned self] in here to prevent a strong reference cycle)

When you initialize a person, their personal greeting hasn’t been created yet:

let person = Person(name: "John Doe")
// person.personalizedGreeting is nil

But when you attempt to print out the personalized greeting, it’s calculated on-the-fly:

NSLog(person.personalizedGreeting)
// personalizedGreeting is calculated when used
// and now contains the value "Hello, John Doe!"

Another good time to use lazy initialization is when the initial value for a property is computationally intensive.

For example, if you have an object that performs some really intense algorithm to determine the number of faces in a picture, make the numberOfFaces property lazily initialized.

Or if you had a class that calculates several different large numbers, you would want to make sure they’re only calculated on-demand:

class MathHelper {

    lazy var pi: Double = {
        // Calculate pi to a crazy number of digits
        return resultOfCalculation
        }()

}

Conclusion

Direct support for lazy property initialization is just one of the many great features of Swift. In the next few months, I’ll cover more great features and shortcuts. Stay tuned!

Updated 7/23/14: Updated to reflect the @lazy attribute being changed to lazy. Also updated to the new Array declaration syntax.

http://mikebuss.com/2014/06/22/lazy-initialization-swift/

原文地址:https://www.cnblogs.com/feng9exe/p/9044789.html

时间: 2024-10-10 18:42:28

Lazy Initialization with Swift的相关文章

Swift中懒加载(lazy initialization)的实现

Swift中是存在和OC一样的懒加载机制的,但是这方面国内的资料比较少,今天把搜索引擎换成了Bing后发现用Bing查英文\最新资料要比百度强上不少. 我们在OC中一般是这样实现懒加载初始化的: 1: @property (nonatomic, strong) NSMutableArray *players; 2:   3: - (NSMutableArray *)players { 4: if (!_players) { 5: _players = [[NSMutableArray alloc

Effective Java 71 Use lazy initialization judiciously

Lazy initialization - It decreases the cost of initializing a class or creating an instance, at the expense of increasing the cost of accessing the lazily initialized field. Depending on what fraction of lazily initialized fields eventually require i

单例模式的两种实现方式对比:DCL (double check idiom)双重检查 和 lazy initialization holder class(静态内部类)

首先这两种方式都是延迟初始化机制,就是当要用到的时候再去初始化. 但是Effective Java书中说过:除非绝对必要,否则就不要这么做. 1. DCL (double checked locking)双重检查: 如果出于性能的考虑而需要对实例域(注意这个属性并没有被static修饰)使用延迟初始化,就使用双重检查模式 public class Singleton { private volatile Singleton uniqueInstance; private Singleton(){

Double-check idiom for lazy initialization of instance fields

Swift singleton && Lazy initializition

偷个懒,看到了个比较靠谱的答案,直接复制过来了. 原网址:http://stackoverflow.com/questions/24024549/dispatch-once-singleton-model-in-swift From my short experience with Swift there are three approaches to implement the Singleton pattern that support lazy initialization and thr

swift 延迟加载

iOS Developer Lazy Initialization with Swift 22 Jun 2014 ? ∞       Lazy initialization (also sometimes called lazy instantiation, or  lazy loading) is a technique for delaying the creation of an object or  some other expensive process until it's need

[Swift]Day10:属性

属性 延时存储属性 Objective-C 的做法 有时候我们需要延时加载属性,在 Objective-C 中可以通过重写 getter 方法实现: @property (nonatomic, strong) NSMutableArray *players; - (NSMutableArray *)players { if (!_players) { _players = [[NSMutableArray alloc] init]; } return _players; } Swift 的新关键

Swift 实现单例模式Singleton pattern的三种方法

转自:点击打开链接 From my short experience with Swift there are three approaches to implement the Singleton pattern that support lazy initialization and thread safety. These approaches might change or become redundant as the language matures. Global constant

Swift学习之路五(构造过程Initialization)

写在前面 喜欢我们的内容,可以订阅我们的官方微信公众账号:乐Coding.我们的iOS高级开发QQ群:386572485. 构造过程(Initialization),Swift中的构造器和Objective-C中的构造函数还是有很大不同的.即使Swift中类的构造器和值类型 (枚举和结构体)的构造器也有所不同. 下面我们慢慢看到底有那些不同. 1. 构造器,构造过程包括为实例中的每个属性设置初始值和为其执行必要的准备和初始化任务: 与 Objective-C 中的构造器不同,Swift 的构造器