- //下面看一个天气预报的例子
- class WeatherReport {
- let location: String let weather: String
- var temperature: Int ? //定义为可选,并不是所有人都关系温度.
- //因为该计算属性使用到闭包,并且闭包中使用到了self,所以必然是惰性属性.
- lazy
- var reports: () - >String = { //使用闭包赋值给reports属性,该属性类型为() -> String(可以理解为匿名函数也就是闭包).
- if self.temperature != nil {
- return "\(self.location)的天气预报是:\(self.weather),气温是:\(self.temperature)"
- } else {
- return "\(self.location)的天气预报是:\(self.weather)"
- }
- }
- init(location: String, weather: String) {
- self.location = location self.weather = weather
- }
- //如果该实例可以被 ARC 回收,则必然调用,否则说明该实例依然存在.
- deinit {
- print("\(location)的天气预报实例被销毁了!")
- }
- }
- func testFive() {
- var weatherReport: WeatherReport ? =WeatherReport(location: "成都", weather: "多云") print("\(weatherReport!.reports())") //这句话告诉 ARC 该类可以被回收了.
- weatherReport = nil
- /*
- 打印结果:
- 成都的天气预报是:多云
- 分析:
- 1:当使用闭包去初始化一个类属性时,该属性前必须加lazy进行修饰,否则将不能够在闭包体内访问该类中的其他属性和方法,因为当闭包段代码被执行时,类是实例还没有完成初始化,self不起作用,另外及时加了 lazy修饰符,在闭包中不能隐式地访问self属性,必须显示的写出来.
- 2:在执行weatherReport = nil代码后,我们告诉 ARC 这个实例不用了,但是我们并没有获得相应的打印信息,因为有强引用环存在,那就是() -> String闭包任然作为强引用指向weatherReport的实例,所以 ARC 放弃了回收,从而造成内存泄露.
- */
- }
- //现在改成如下代码:
- class WeatherReport { let location: String let weather: String
- var temperature: Int ? //定义为可选,并不是所有人都关系温度.
- //因为该计算属性使用到闭包,并且闭包中使用到了self,所以必然是惰性属性.
- // lazy var reports:() -> String = { //使用闭包赋值给reports属性,该属性类型为() -> String(可以理解为匿名函数也就是闭包).
- // [unowned self] in
- // if self.temperature != nil{
- //
- // return "\(self.location)的天气预报是:\(self.weather),气温是:\(self.temperature)"
- // }else{
- //
- // return "\(self.location)的天气预报是:\(self.weather)"
- // }
- // }
- /*
- 注意:如果闭包体当前实例未来永远不会为nil,那么使用无主类型,否则使用弱引用捕获类型,像这里,最好使用弱引用类型,因为该实例不会一直存在,只是用完了就释放掉了.
- */
- lazy
- var reports: () - >String = { [weak self] in
- if self ! .temperature != nil {
- return "\(self!.location)的天气预报是:\(self!.weather),气温是:\(self!.temperature)"
- } else {
- return "\(self!.location)的天气预报是:\(self!.weather)"
- }
- } init(location: String, weather: String) { self.location = location self.weather = weather
- } //如果该实例可以被 ARC 回收,则必然调用,否则说明该实例依然存在.
- deinit { print("\(location)的天气预报实例被销毁了!")
- }
- }打印如下: 成都的天气预报是: 多云成都的天气预报实例被销毁了 !
- /*
- 当我们在闭包体内添加[unowned self] in之后,可以看到打印如下:
- 成都的天气预报是:多云
- 成都的天气预报实例被销毁了!
- 调用了类的deinit方法,[unowned self]该语句就是捕获列表,其主要用途就是打破强引用关系,直接告诉Swift说这个闭包是普通的闭包,闭包中的self是对实例的无主引用,不会通过 ARC 保存这个实例.
- 注意捕获列表的几种格式:
- 普通的闭包前没有捕获列表都是强引用关系.
- lazy var comeClosure(参数列表) -> 返回类型{
- //闭包题
- }
- 标准的闭包体加捕获列表
- lazy var someClosureWithCaptureList(参数列表) -> 返回类型{
- [捕获列表类型 捕获对象](参数) -> 返回类型 in
- //闭包体
- }
- 注意:
- 捕获列表类型 可以是weak,也可以是 unowned
- 捕获对象 代表具体的类实例,如 self或者otherInstance,如果有多个实例需要慎重引用类型,中间使用逗号隔开如:[unowned self,weak otherInstance].
- 如果闭包本身没有参数列表,简化如下:
- lazy var someClosureWithCaptureList(参数列表) -> 返回类型{
- [捕获列表类型 捕获对象] in
- //闭包体
- }
- */
来源: http://lib.csdn.net/snippet/swift/44257