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/

Lazy Initialization with Swift的更多相关文章

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

    Swift中是存在和OC一样的懒加载机制的,但是这方面国内的资料比较少,今天把搜索引擎换成了Bing后发现用Bing查英文\最新资料要比百度强上不少. 我们在OC中一般是这样实现懒加载初始化的: 1: ...

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

    首先这两种方式都是延迟初始化机制,就是当要用到的时候再去初始化. 但是Effective Java书中说过:除非绝对必要,否则就不要这么做. 1. DCL (double checked lockin ...

  3. Effective Java 71 Use lazy initialization judiciously

    Lazy initialization - It decreases the cost of initializing a class or creating an instance, at the ...

  4. Swift - 懒加载(lazy initialization)

    Swift中是存在和OC一样的懒加载机制的,在程序设计中,我们经常会使用 懒加载 ,顾名思义,就是用到的时候再开辟空间 懒加载 格式: lazy var 变量: 类型 = { 创建变量代码 }() 懒 ...

  5. Double-check idiom for lazy initialization of instance fields

  6. 单例模式-Lazy initialization holder class模式

    这个模式综合使用了Java的类级内部类和多线程缺省同步锁的知识,很巧妙地同时实现了延迟加载和线程安全. 1.相应的基础知识 什么是类级内部类? 简单点说,类级内部类指的是,有static修饰的成员式内 ...

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

    转自:点击打开链接 From my short experience with Swift there are three approaches to implement the Singleton ...

  8. Awesome Swift

    Awesome Swift https://github.com/matteocrippa/awesome-swift A collaborative list of awesome Swift re ...

  9. [你必须知道的.NET]第三十三回,深入.NET 4.0之,Lazy<T>点滴

    发布日期:2009.10.29 作者:Anytao © 2009 Anytao.com ,Anytao原创作品,转贴请注明作者和出处. 对象的创建方式,始终代表了软件工业的生产力方向,代表了先进软件技 ...

随机推荐

  1. Java基本类型转换

    1.自动类型转换 java所有的数值型变量都可以相互转换,如果系统支持把某种基本类型的值直接付赋给另一个基本类型的变量,则这种方式被称为自动类型转换. 当把一个表数范围小的数值或变量直接赋给另一个表数 ...

  2. jquery判断字符串中是否存在某个的字符串

    有两种方式: 1)test 2)indexOf $(function(){ var str="sunny,woo"; var sear=new RegExp(','); if(se ...

  3. PHP多进程初探 --- 利用多进程开发点儿东西吧

    [原文地址:https://blog.ti-node.com/blog...] 干巴巴地叨逼叨了这么久,时候表演真正的技术了! 做个高端点儿的玩意吧,加入我们要做一个任务系统,这个系统可以在后台帮我们 ...

  4. Python 设置字体样式

    # 1.先导入分别可指定单元格字体相关,颜色,和对齐方式的类 from openpyxl.styles import Font, colors, Alignment # 2.配置字体格式为:样式(Ti ...

  5. bzoj 2654 && bzoj 3675 总结

    手动博客搬家: 本文发表于20180929 15:18:55, 原地址https://blog.csdn.net/suncongbo/article/details/82897992 最近做到了两道( ...

  6. 【codeforces 793C】Mice problem

    [题目链接]:http://codeforces.com/contest/793/problem/C [题意] 给你每个点x轴移动速度,y轴移动速度; 问你有没有某个时刻,所有的点都"严格& ...

  7. hdu 3352 求边双联通分量模板题(容器)

    /*这道题是没有重边的,求加几条边构成双联通,求边联通分量,先求出桥然后缩点,成一个棵树 找叶子节点的个数*/ #include<stdio.h> #include<string.h ...

  8. elasticsearch6.4中文文档

    男朋友翻译的,我这边做一个查看入口,分享给大家,O(∩_∩)O哈哈~ 版权声明:本文为博主原创文章,无需授权即可转载,甚至无需保留以上版权声明,转载时请务必注明作者. https://blog.csd ...

  9. 数据库工具——Navicat Premium使用技巧

    Navicat Premium 常用功能讲解 1.快捷键 1.1. F8 快速回到当前对象列表  1.2. Ctrl + q 打开查询界面  1.3. Ctrl + d 快速修改当前的表结构  1.4 ...

  10. SQLSERVER--存储过程--示例

    存储过程 CREATE PROCEDURE addUser --Add the parameters for the stored procedure here (--存储过程参数 @系统类别 nva ...