• linkedu视频
  • 平面设计
  • 电脑入门
  • 操作系统
  • 办公应用
  • 电脑硬件
  • 动画设计
  • 3D设计
  • 网页设计
  • CAD设计
  • 影音处理
  • 数据库
  • 程序设计
  • 认证考试
  • 信息管理
  • 信息安全
菜单
linkedu.com
  • 网页制作
  • 数据库
  • 程序设计
  • 操作系统
  • CMS教程
  • 游戏攻略
  • 脚本语言
  • 平面设计
  • 软件教程
  • 网络安全
  • 电脑知识
  • 服务器
  • 视频教程
  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号
您的位置:首页 > 程序设计 >swift > 实例讲解Swift中引用类型的ARC自动引用计数

实例讲解Swift中引用类型的ARC自动引用计数

作者:珲少 字体:[增加 减小] 来源:互联网 时间:2017-05-28

珲少 通过本文主要向大家介绍了swift信用证实例,swift开发实例,swift 实例,swift报文类型,swift类型转换等相关知识,希望对您有所帮助,也希望大家支持linkedu.com www.linkedu.com

一、引言

ARC(自动引用计数)是Objective-C和Swift中用于解决内存管理问题的方案。在学习Objective-C编程时经常会学习到一个关于ARC的例子:在一个公用的图书馆中,每次进入一人就将卡插入,走的时候将自己的卡拔出拿走。图书馆系统会判定只要有卡插入,就将图书馆的灯打开,当所有卡都被取走后,将图书馆的灯关掉。这个例子对应于Objective-C中的对象声明周期管理十分贴切。每当一个对象增加一个引用时,其引用计数会加1,当一个引用被取消时,对象的引用计数减1,当引用计数减为0时,说明此对象将不再有任何引用,对象会被释放掉,让出内存。Swift也采用同样的方式进行内存管理。

注意:在Swift中只有引用类型有自动引用计数,结构体、枚举这类值类型是没有引用计数的。关于引用计数的示例代码如下:

class MyClass {
  deinit{
    print("MyClass deinit")
  }
}
var cls1:MyClass? = MyClass()
var cls2:MyClass? = cls1
var cls3:MyClass? = cls2
cls2 = nil
cls1 = nil
//执行下面代码后才会打印“MyClass deinit”
cls3 = nil
</div>

二、循环引用的处理方法

在开发中,开发者一不小心就会写出产生循环引用的代码,在上面的示例中可以看出,除非实例的引用全部解除,否则实例将不会调用析构方法,内存不会被释放,如果在写代码时,A引用了B,同样B也引用了A,那么实际上现在A和B的引用计数都是2,将A和B都置为nil后,A和B实例依然保有1个引用计数,都不会被释放,实例如下:

class MyClassOne {
  var cls:MyClassTwo?
  deinit{
    print("ClassOne deinit")
  }
}
class MyClassTwo {
  var cls:MyClassOne?
  deinit{
    print("ClassTwo deinit")
  }
}
var obj1:MyClassOne? = MyClassOne()
var obj2:MyClassTwo? = MyClassTwo()
obj1?.cls = obj2
obj2?.cls = obj1
obj1=nil
obj2=nil
//没有打印析构函数的调用信息
</div>

对于上面的情况,可以将属性声明称weak类型来防止这种循环引用,weak的作用在于只是弱引用实例,原实例的引用计数并不会加1,示例如下:

//关于弱引用的演示
class MyClassThree{
  weak var cls:MyClassFour?
  deinit{
    print("ClassThree deinit")
  }
}
class MyClassFour {
  var cls:MyClassThree?
  deinit{
    print("ClassFour deinit")
  }
}
var obj3:MyClassThree? = MyClassThree()
var obj4:MyClassFour? = MyClassFour()
obj3?.cls = obj4
obj4?.cls = obj3
obj4=nil
//此时obj3中的cls也为nil
obj3?.cls
</div>

若引用的实例被释放后,其在另一个实例中的引用也将被置为nil,所以weak只能用于optional类型的属性,然而在开发中还有一种情况,某个类必须保有另一个类的示例,这个实例不能为nil,但是这个属性又不能影响其原始实例的释放,这种情况也会造成循环引用,示例如下:

class MyClassFive{
  var cls:MyClassSix
  init(param:MyClassSix){
    cls = param
  }
  deinit{
    print("ClassFive deinit")
  }
}
class MyClassSix{
  var cls:MyClassFive?
  deinit{
    print("ClassSix deinit")
  }
}
var obj6:MyClassSix? = MyClassSix()
var obj5:MyClassFive? = MyClassFive(param: obj6!)
obj6?.cls = obj5
obj5=nil
obj6=nil
//没有打印任何信息
</div>

上面的示例也会造成循环引用,然而MyClassFive类中的cls属性为常量不可为nil,不可使用weak弱引用来做Swift中又提供了一个关键字unowned无主引用来处理这样的问题,示例如下:

class MyClassFive{
  unowned var cls:MyClassSix
  init(param:MyClassSix){
    cls = param
  }
  deinit{
    print("ClassFive deinit")
  }
}
class MyClassSix{
  var cls:MyClassFive?
  deinit{
    print("ClassSix deinit")
  }
}
var obj6:MyClassSix? = MyClassSix()
var obj5:MyClassFive? = MyClassFive(param: obj6!)
obj6?.cls = obj5
obj5=nil
obj6=nil
</div>

关于弱引用和无主引用,其区别主要是在于:

1.弱引用用于解决Optional值的引起的循环引用。

2.无主引用用于解决非Optional值引起的循环引用。

3.个人以为,弱引用可用下图表示:

201677181603163.png (1516×724)

4.无主引用可用如下图表示:

201677181654671.jpg (1516×724)

若将上面的代码修改如下,程序会直接崩溃:

class MyClassFive{
  unowned var cls:MyClassSix
  init(param:MyClassSix){
    cls = param
  }
  deinit{
    print("ClassFive deinit")
  }
}
class MyClassSix{
  var cls:MyClassFive?
  deinit{
    print("ClassSix deinit")
  }
}
var obj6:MyClassSix? = MyClassSix()
var obj5:MyClassFive? = MyClassFive(param: obj6!)
obj6?.cls = obj5
obj6=nil
obj5?.cls
</div>

上面所举的例子满足了两种情况,一种是两类实例引用的属性都是Optional值的时候使用weak来解决循环引用,一种是两类实例有一个为非Optional值的时候使用unowned来解决循环引用,然而还有第三种情况,两类实例引用的属性都为非Optional值的时候,可以使用无主引用与隐式拆包结合的方式来解决,这也是无主引用最大的应用之处,示例如下:

class MyClassSeven{
  unowned var cls:MyClassEight
  init(param:MyClassEight){
    cls = param
  }
  deinit{
    print("ClassSeven deinit")
  }
}
class MyClassEight{
  var cls:MyClassSeven!
  init(){
    cls = MyClassSeven(param:self)
  }
  deinit{
    print("ClassEight deinit")
  }
}
var obj7:MyClassEight? = MyClassEight()
obj7=nil
</div>

除了在两个类实例间会产生循环引用,在闭包中,也可能出现循环引用,当某个类中包含一个闭包属性,同时这个闭包属性中又使用了类实例,则会产生循环引用,示例如下:

class MyClassNine {
  var name:String = "HS"
  lazy var closure:()->Void = {
    //闭包中使用引用值会使引用+1
    print(self.name)
  }
  deinit{
    print("ClassNine deinit")
  }
}
var obj9:MyClassNine? = MyClassNine()
obj9?.closure()
obj9=nil
//不会打印析构信息
</div>

Swift中提供了闭包的捕获列表来对引用类型进行弱引用或者无主引用的转换:

class MyClassNine {
  var name:String = "HS"
  lazy var closure:()->Void = {
    [unowned self]()->Void in
    print(self.name)
  }
  deinit{
    print("ClassNine deinit")
  }
}
var obj9:MyClassNine? = MyClassNine()
obj9?.closure()
obj9=nil
</div>

捕获列表以中括号标识,多个捕获参数则使用逗号分隔。

</div>
分享到:QQ空间新浪微博腾讯微博微信百度贴吧QQ好友复制网址打印

您可能想查找下面的文章:

  • Swift UILable 设置内边距实例代码
  • 实例讲解Swift中引用类型的ARC自动引用计数
  • Swift编程中的switch...case语句实例解析
  • Swift与C语言指针结合使用实例
  • Swift中动态调用实例方法介绍
  • Swift调用Objective-C编写的API实例

相关文章

  • 2017-05-28Swift、Objective-C、Cocoa混合编程设置指南
  • 2017-05-22Swift 字符串
  • 2017-05-28Swift使用WKWebView在iOS应用中调用Web的方法详解
  • 2017-05-28深入讲解Swift的内存管理
  • 2017-05-28MyBatis中SqlSession实现增删改查案例
  • 2017-05-28Servlet3.0实现文件上传的方法
  • 2017-05-28Swift的函数式编程详解
  • 2017-05-28Swift教程之继承详解
  • 2017-05-22Swift 字符(Character)
  • 2017-05-28详解Swift编程中的for循环的编写方法

文章分类

  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号

最近更新的内容

    • Swift教程之类的析构详解
    • MyBatis中的模糊查询语句
    • 详解Swift中的数据类型类型转换
    • Swift 变量
    • Swift学习笔记之元组(tuples)
    • Swift中 !和 ?的区别及使用
    • Swift项目中利用SWRevealViewController实现侧滑菜单
    • Swift 中闭包的简单使用
    • Swift3.0仿支付宝二维码扫描效果
    • 详解Swift编程中下标的用法

关于我们 - 联系我们 - 免责声明 - 网站地图

©2020-2025 All Rights Reserved. linkedu.com 版权所有