Swift中的懒加载—@lazy

        Swift中的延迟加载是一种将对象的创建或其它高负荷操作延迟到真正需要时才执行的机制。当为iOS进行编程时,仅在需要时才分配内存,对小内存的手机而言(相对于电脑)非常实用。

Objective-C中的延迟加载

在Objecitve-C中,如果你要延迟加载一个可变数组,你需要这么做:

@property (nonatomic, strong) NSMutableArray *players;

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

Objective-C初学者要理解这个机制首先要知道getter方法名必须跟属性名一致。如果你拼写错了,这个机制会失效,每次访问players会返回nil

他们还需要知道_players实例变量是在属性同步时默认创建的,需要在属性名前加上下划线,才能访问到这个实例变量。

这些对初学者来说都不那么直观。

Swift方式的延迟加载

而在Swift中,你只需一行代码即可实现此机制:

lazy var players = String[]()

简单、简洁,直入主题。

但你得记住,你必须使用var关键字来定义延迟加载的属性,不能使用let关键字,因为常量必须在实例构建时赋值。

如果你想给延迟加载加上一些逻辑处理,Swift允许你在属性后面定义一个闭包调用(闭包的返回值会作为属性的默认值):

(1)

lazy var text:UITextField = {

var text = UITextField()

        text = UITextField(frame: CGRectMake(100, 100, 100, 100))

        text.backgroundColor = UIColor.redColor()

        text.placeholder = "姓名"

        text.delegate = self

        return text

        }()

如果你愿意,你也可以使用实例方法来初始化延迟加载属性:

(2)

lazy var players: String[] = self.initialPlayers()
func initialPlayers() -> String[] {
    var players = ["Mike Buss"]
    return players
}

或者用个类方法也可以:

(3)

lazy var players = MultipeerManager.initialPlayers()
class func initialPlayers() -> String[] {
    var players = ["Mike Buss"]
    return players
}

但大家现在更倾向于使用新的闭包语法,因为它将逻辑代码就定义在了属性声明的旁边。

何时使用延迟加载?

一种使用场景是,一个对象的属性的初始值依赖与其它的属性,所以必须先创建出这个对象,才能知道这个属性的值。

举例来说,你有一个Person类以及一个personalizedGreeting属性。这个personalizedGreeting属性需要在对象创建完成后才延迟加载,因为只有在对象创建完成后它才能知道问候的人是谁(person的name)。请看代码:

class Person {

    var name: String

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

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

注意,你必须使用 [unowned self]来避免循环引用。[unowned self]定义了一个在闭包中需要使用的、存在于闭包外的属性/变量列表,又叫捕获列表(capture list)。

当你实例化一个person时,他的问候语greeting此时并没有创建:

let person = Person(name: "Robert Redford)
// person.personalizedGreeting is nil

但是当你尝试打印出问候语时,这句问候语会自动生成出来:

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

另一种适合延迟加载的场景,是在属性的初始值需要进行大量计算之时。

举例来说,当你有个对象需要执行一个高负荷的算法来确定一张图片中的人脸个数,你可以将numberOfFaces属性设置为延迟加载。

或者当你有个类需要计算多个大数的值,你希望它们能在需要的时候才被计算出来:

class MathHelper {

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

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值