当前位置: 首页 > 教程 > Swift >

Swift ARC简述

精华
小牛编辑
115浏览
2023-03-14

Swift 4语言中内存管理功能及用法通过自动引用计数(ARC)来处理。 ARC用于初始化和取消初始化系统资源,从而在不再需要实例时释放类实例使用的内存空间。 ARC会跟踪有关代码实例之间关系的信息,以便有效地管理内存资源。

ARC的功能特性

  • ARC分配一块内存来存储每次由init()创建新类实例时的信息。
  • 有关实例类型及其值的信息存储在内存中。
  • 当不再需要类实例时,它会通过deinit()自动释放内存空间,以进行进一步的类实例存储和检索。
  • ARC跟踪当前引用的类实例属性,常量和变量,以便deinit()仅应用于那些未使用的实例。
  • ARC保持对那些类实例属性,常量和变量的“强引用”,以在当前使用类实例时限制释放。

ARC程序

class StudDetails {
   var stname: String!
   var mark: Int!

   init(stname: String, mark: Int) {
      self.stname = stname
      self.mark = mark
   }
   deinit {
      print("Deinitialized \(self.stname)")
      print("Deinitialized \(self.mark)")
   }
}

let stname = "Swift 4"
let mark = 98

print(stname)
print(mark)

当使用playground 运行上述程序时,得到以下结果 -

Swift 4
98

ARC强引用循环类实例

class studmarks {
   let name: String
   var stud: student?

   init (name: String) {
      print("Initializing: \(name)")
      self.name = name
   }
   deinit {
      print("Deallocating: \(self.name)")
   }
}

class student {
   let name: String
   var strname: studmarks?

   init (name: String) {
      print("Initializing: \(name)")
      self.name = name
   }
   deinit {
      print("Deallocating: \(self.name)")
   }
}

var shiba: studmarks?
var mari: student?

shiba = studmarks(name: "Swift 4")
mari = student(name: "ARC")

shiba!.stud = mari
mari!.strname = shiba

当使用playground 运行上述程序时,得到以下结果 -

Initializing: Swift 4
Initializing: ARC

ARC弱和无主引用

类类型属性有两种方法可以解决强引用周期 -

  • 弱引用
  • 无主引用

这些引用用于使一个实例能够引用参考周期中的其他实例。 然后,实例可以参考每个实例而不是关注强引用循环。 当用户知道某个实例可能返回nil值时,可指出使用弱引用。 当实例返回某些内容而不是nil时,则使用无主引用声明它。

弱引用程序

class module {
   let name: String
   init(name: String) { self.name = name }
   var sub: submodule?
   deinit { print("\(name) Is The Main Module") }
}

class submodule {
   let number: Int
   init(number: Int) { self.number = number }
   weak var topic: module?

   deinit { print("Sub Module with its topic number is \(number)") }
}

var toc: module?
var list: submodule?
toc = module(name: "ARC")
list = submodule(number: 4)
toc!.sub = list
list!.topic = toc

toc = nil
list = nil

当使用playground 运行上述程序时,得到以下结果 -

ARC Is The Main Module
Sub Module with its topic number is 4

无主引用程序

class student {
   let name: String
   var section: marks?
   init(name: String) {
      self.name = name
   }
   deinit { print("\(name)") }
}

class marks {
   let marks: Int
   unowned let stname: student

   init(marks: Int, stname: student) {
      self.marks = marks
      self.stname = stname
   }
   deinit { print("Marks Obtained by the student is \(marks)") }
}

var module: student?
module = student(name: "ARC")
module!.section = marks(marks: 98, stname: module!)
module = nil

当使用playground 运行上述程序时,得到以下结果 -

ARC
Marks Obtained by the student is 98

闭包的强引用周期

当要为类实例属性和闭包的主体分配闭包以捕获特定实例时,可能会发生强引用周期。 对闭包的强引用由self.somePropertyself.someMethod()定义。 强引用周期用作闭包的引用类型。

class HTMLElement {
   let samplename: String
   let text: String?

   lazy var asHTML: () -> String = {
      if let text = self.text {
         return "<\(self.samplename)>\(text)</\(self.samplename)>"
      } else {
         return "<\(self.samplename) />"
      }
   }
   init(samplename: String, text: String? = nil) {
      self.samplename = samplename
      self.text = text
   }
   deinit {
      print("\(samplename) is being deinitialized")
   }
}

var paragraph: HTMLElement? = HTMLElement(samplename: "p", text: "Welcome to Closure SRC")
print(paragraph!.asHTML())

当使用playground 运行上述程序时,得到以下结果 -

<p>Welcome to Closure SRC</p>

弱和无主引用

当闭包和实例相互引用时,用户可以将闭包中的捕获定义为无主引用。 然后它不允许用户同时解除分配实例。 当实例有时返回nil值时,用弱实例定义闭包。

class HTMLElement {
   let module: String
   let text: String?

   lazy var asHTML: () -> String = {
      [unowned self] in
      if let text = self.text {
         return "<\(self.module)>\(text)</\(self.module)>"
      } else {
         return "<\(self.module) />"
      }
   }
   init(module: String, text: String? = nil) {
      self.module = module
      self.text = text
   }
   deinit {
      print("\(module) the deinit()")
   }
}

var paragraph: HTMLElement? = HTMLElement(module: "Inside", text: "ARC Weak References")
print(paragraph!.asHTML())
paragraph = nil

当使用playground 运行上述程序时,得到以下结果 -

<Inside>ARC Weak References</Inside>
Inside the deinit()

最后更新:

类似资料

  • Redis为一个运行在内存中的数据结构服务器(data structures server)。Redis使用的是单进程(除持久化时),所以在配置时,一个实例只会用到一个CPU。本手册分为三部分,第一部分从开发角度介绍了redis开发中使用API、场景和生产设计规范最佳实践,第二部分从运维角度介绍了如何运维redis,其间的常见操作和最佳实践等,第三部分是从高可用和集群方面介绍了redis相关的集群

  • collectd 是一个守护(daemon)进程,用来收集系统性能和提供各种存储方式来存储不同值的机制。它会在系统运行和存储信息时周期性的统计系统的相关统计信息。利用这些信息有助于查找当前系统性能瓶颈(如作为性能分析 performance analysis)和预测系统未来的 load(如能力部署capacity planning)等 下面简单介绍一下: collectd的部署以及与logstas

  • 1、编码 如无特殊情况, 文件一律使用 UTF-8 编码 如无特殊情况, 文件头部必须加入#-*-coding:utf-8-*-标识 2、代码格式 2.1、缩进 统一使用 4 个空格进行缩进 2.2、行宽 每行代码尽量不超过 80 个字符(在特殊情况下可以略微超过 80 ,但最长不得超过 120) 理由: 这在查看 side-by-side 的 diff 时很有帮助 方便在控制台下查看代码 太长可

  • CSS是Cascading Style Sheets的缩写,翻译过来叫做层叠样式表,一般简称为样式表,但通常大家还是习惯叫CSS。 最初的HTML很单一,甚至无法显示图片,随着使用范围越来越广泛,HTML支持的标签开始多了起来,所支持的样式也开始增多。但是把样式完全交给HTML去做不是一个好想法,因为HTML更侧重于页面的结构,于是在1994年CSS被提出。CSS旨在对HTML元素的外观加以描述,

  • DOM是Document Object Model的缩写,翻译过来叫文档对象模型,但我觉得这个听起来很生疏,不如还是直接叫DOM,所以本节的标题就定为了DOM简述。由于Chrome扩展应用使用HTML渲染界面,所以不可避免地要接触DOM。考虑到并非所有读者都编写过HTML,我决定单独拿出一小节来讲解DOM,帮助这些读者快速入门。当然,用短短的一节是无法讲透的——毕竟DOM可以写另外一本书了——这里

  • 译序 不懂数据库的全栈工程师不是好架构师 —— Vonng ​ 现今,尤其是在互联网领域,大多数应用都属于数据密集型应用。本书从底层数据结构到顶层架构设计,将数据系统设计中的精髓娓娓道来。其中的宝贵经验无论是对架构师,DBA、还是后端工程师、甚至产品经理都会有帮助。 ​ 这是一本理论结合实践的书,书中很多问题,译者在实际场景中都曾遇到过,读来让人击节扼腕。如果能早点读到这本书,该少走多少弯路啊!