循环强引用还会发生在当你将一个闭包赋值给类实例的某个实例,并且这个闭包体中又实用了这个类实例。这个闭包体重可能访问了实例的某个属性,例如self.**,或者闭包中调用了实例的某个方法,例如self.**,这两种情况都导致闭包“捕获”self,从而产生了循环强引用。

  循环强引用的产生,是因为闭包和类相似,都是引用类型。当你把闭包赋值给某个属性时,你也把一个引用赋值给了这个闭包。实质上,这跟之前的问题一样,两个强引用让彼此一直有效。但是,和两个类实例不同,这次一个是类实例,另一个是闭包。

  Swift提供了一种优雅的方法来解决这个问题,称之为闭包捕获列表。

  在定义闭包时,同时定义捕获列表作为闭包的一部分,通过这种方式可以解决闭包和类实例之间的循环强引用。捕获列表定义了闭包体内捕获一个或者多个引用类型的规则。跟解决两个类实例间的循环强引用一样,声明每个捕获的引用为弱引用或无主易用,而不是强引用。应该根据代码关系来决定使用弱引用还是无主引用。

  ----------定义捕获列表

  捕获列表中的每一项都由一对元素组成,一个元素是weak或unowned关键字,另一个元素是类实例的引用(如self)或初始化过的变量(如delegate = self.delegate!)。这些项在方括号中用逗号分开。

  如果闭包有参数列表和返回类型,把捕获列表放在它们前面:

  如果闭包没有指明参数列表或者返回类型,即他们会通过上下文来判断,那么可以把捕获列表和关键字in放在闭包最开始的地方。

  ----------弱引用和无主引用

  在闭包和捕获的实例总是互相引用时并且总是同时销毁时,将闭包内的捕获定义为无主引用。

  相反的,在被捕获的引用可能会变为nil时,将闭包内的捕获定义为弱引用。弱引用总是可选类型,并且当引用的实例被销毁后,弱引用的值会自动置为nil。这使我们可以在闭包体内检查他们是否存在。

  注意:如果被捕获的引用绝对不会变为nil,应该用无主引用,而不是弱引用。

class HTMLElement {
let name:String
let text:String? lazy var asHTML:Void -> String = {
[unowned self] in //表示“用无主引用而不是强引用来捕获 self ”
if let text = self.text{
return "<\(self.name)> \(text)<\(self.name)>"
}else{
return "<\(self.name)>"
}
} init(name:String, text:String? = nil){
self.name = name
self.text = text
} deinit{
print("\(name) is being deinitialized")
}
} var paragraph:HTMLElement? = HTMLElement(name: "p", text: "hello world")
print(paragraph!.asHTML())

  打印:

<p> hello world<p>

这个闭包这个地方,没有看懂。

Swift-08-闭包引起的循环强引用的更多相关文章

  1. Swift - 内存泄露原因(循环强引用)及解决办法

    Swift使用自动引用计数(ARC)来管理应用程序的内存使用.在大多是情况下,并不需要考虑内存的管理.当实例不再需要的时候,ARC会自动释放这些实例所使用的内存. 但ARC并不是绝对安全的.下面两种情 ...

  2. Swift 学习笔记 (三) 之循环引用浅析

    原创:转载请注明出处 110.自动引用计数实践 下面的例子展示了自动引用计数的工作机制.例子以一个简单的Person类开始,并定义了一个叫name的常量属性: class Person {     l ...

  3. 弱引用?强引用?未持有?额滴神啊-- Swift 引用计数指导

    ARC ARC 苹果版本的自动内存管理的编译时间特性.它代表了自动引用计数(Automatic Reference Counting).也就是对于一个对象来说,只有在引用计数为0的情况下内存才会被释放 ...

  4. Swift 学习- 08 -- 闭包

    // 闭包是自包含的函数代码块, 可以在代码中被传递和使用, swift 中的闭包 与 C语言 和 OC 中的代码块 (blocks) 以及其他一些编程语言中的匿名函数比较类似 // 闭包可以捕获和存 ...

  5. Swift入门(十)——循环引用、弱引用和无主引用

    近期看到swift里面不仅有循环引用和弱引用(weak),还加入了无主引用(unowned),于是写了一些demo,这里总结一下. 和OC一样.Swfit默认也是基于ARC进行内存管理的,因此尽管简单 ...

  6. Swift:闭包(Closures)

    一. 基本概念 闭包(Closures)是自包括的功能代码块,能够在代码中使用或者用来作为參数传值. 在Swift中的闭包与C.OC中的blocks和其他编程语言(如C#)中的lambda, java ...

  7. iOS - Swift Closure 闭包

    1.Closure 闭包在 Swift 中非常有用.通俗的解释就是一个 Int 类型里存储着一个整数,一个 String 类型包含着一串字符,同样,闭包是一个包含着函数的类型.有了闭包,你就可以处理很 ...

  8. Swift的闭包(二):捕获值

    闭包可以从定义它的上下文中捕获常量和变量. 在Swift中,捕获值最简单的例子是嵌套函数,举个例子: func makeIncrementer(forIncrement amount: Int) -& ...

  9. Swift:闭包

    一.闭包的介绍 闭包表达式(Closure Expressions) 尾随闭包(Trailing Closures) 值捕获(Capturing Values) 闭包是引用类型(Closures Ar ...

随机推荐

  1. CSS Counters 计数属性

    CSS Counters其实就是一计数器,早期在CSS中计数器仅存在于ul和ol元素.如果要使用在div这样的元素上,只能通过list-style-image或者是元素的backgroud-image ...

  2. SpringMVC、Struts1、Struts2和SSH2框架中单例与多例的解析

    struts1是单例提供服务,请求数据绑定在actionform里,form当做参数传入调用方法,不用实例变量就不会出现并发问题. spring mvc的contrller也是这样的模式 struts ...

  3. Why NHibernate updates DB on commit of read-only transaction

    http://www.zvolkov.com/clog/2009/07/09/why-nhibernate-updates-db-on-commit-of-read-only-transaction/ ...

  4. for循环计算游戏通关分数

    一个游戏1到20关是成绩是自身关卡数的成绩,21-30每关10分,31-40每关20分,41-49每关30分,50关100分.输入一个关数求成绩 代码如下: <!DOCTYPE html PUB ...

  5. HDU 2091 空心三角形(模拟)

    把一个字符三角形掏空,就能节省材料成本,减轻重量,但关键是为了追求另一种视觉效果.在设计的过程中,需要给出各种花纹的材料和大小尺寸的三角形样板,通过电脑临时做出来,以便看看效果.   Input 每行 ...

  6. HTML5 javascript CSS3 jQuery Mobile一些好用的网站

    jQueryMobile:学习 http://www.runoob.com/jquerymobile/jquerymobile-tutorial.html 百度 CDN: http://cdn.cod ...

  7. php扩展redis,编译安装redis服务

    首先安装redis扩展 https://github.com/phpredis/phpredis 下载http://redis.io/download 服务软件 cd到软件存放目录unzip phpr ...

  8. hdu1874 最短路模板题

    之所以做了第二道模板题还要写是因为发现了一些自己的问题 用的是dij 最简单的松弛 需要注意的地方是松弛的时候 判断dis[i]<dis[w]+tance[w][i]时 还要再判断 vis[i] ...

  9. #define与运算精度问题探究

    #include <stdio.h> #define SQR(X) X*X int main(int argc, char* argv[]) { ; ; ; printf("SQ ...

  10. anti-pattern - Hard coding

    https://en.wikipedia.org/wiki/Hard_coding Considered an anti-pattern, hard coding requires the progr ...