美文网首页iOSiOS Developerswift
【Swift概念】Swift的内存管理

【Swift概念】Swift的内存管理

作者: devCK凯 | 来源:发表于2016-01-20 18:47 被阅读218次

Swift的内存管理怎么办??

在Objective-C中无论ARC、MRC,开发中我们还是需要对内存进行管理,主要在于,避免循环引用、代理、KVO移除、Block这些,再有就是属性声明时的语义(property_attribute)。关于Objective-C中的引用计数制我就不重复了。
可到了Swift中,对于属性的声明就只剩下了lazy\weak。这个可让这些从Objective-C走来的程序员们一下就犯了难。

一、聊一聊,Swift的内存管理

1、自动引用计数的工作机制

当你每次创建一个类的新的实例的时候,ARC 会分配一大块内存用来储存实例的信息。内存中会包含实例的类型信息,以及这个实例所有相关属性的值。
此外,当实例不再被使用时,ARC 释放实例所占用的内存,并让释放的内存能挪作他用。这确保了不再被使用的实例,不会一直占用内存空间。
然而,当 ARC 收回和释放了正在被使用中的实例,该实例的属性和方法将不能再被访问和调用。实际上,如果你试图访问这个实例,你的应用程序很可能会崩溃。
为了确保使用中的实例不会被销毁,ARC 会跟踪和计算每一个实例正在被多少属性,常量和变量所引用。哪怕实例的引用数为1,ARC都不会销毁这个实例。
为了使上述成为可能,无论你将实例赋值给属性、常量或变量,它们都会创建此实例的强引用。之所以称之为“强”引用,是因为它会将实例牢牢地保持住,只要强引用还在,实例是不允许被销毁的。

2、举个栗子

接下来的代码片段定义了三个类型为Person?的变量,用来按照代码片段中的顺序,为新的Person实例建立多个引用。由于这些变量是被定义为可选类型(Person?,而不是Person),它们的值会被自动初始化为nil,目前还不会引用到Person类的实例。

var reference1: Person?
var reference2: Person?
var reference3: Person?

现在你可以创建Person类的新实例,并且将它赋值给三个变量中的一个:

reference1 = Person(name: "John Appleseed")
// prints "John Appleseed is being initialized”

应当注意到当你调用Person类的构造函数的时候,“John Appleseed is being initialized”会被打印出来。由此可以确定构造函数被执行。
由于Person类的新实例被赋值给了reference1变量,所以reference1到Person类的新实例之间建立了一个强引用。正是因为这一个强引用,ARC 会保证Person实例被保持在内存中不被销毁。
如果你将同一个Person实例也赋值给其他两个变量,该实例又会多出两个强引用:

reference2 = reference1
reference3 = reference1

现在这一个Person实例已经有三个强引用了。
如果你通过给其中两个变量赋值nil的方式断开两个强引用(包括最先的那个强引用),只留下一个强引用,Person实例不会被销毁:

reference1 = nil
reference2 = nil

在你清楚地表明不再使用这个Person实例时,即第三个也就是最后一个强引用被断开时,ARC 会销毁它:

reference3 = nil
// 打印 “John Appleseed is being deinitialized”

3、类实例之间的循环强引用

我们可能会写出一个类实例的强引用数永远不能变成0的代码。如果两个类实例互相持有对方的强引用,因而每个实例都让对方一直存在,就是这种情况。这就是所谓的循环强引用。
你可以通过定义类之间的关系为weak弱引用或unowned无主引用,以替代强引用,从而解决循环强引用的问题。

 let unit: String init(unit: String) {
   self.unit = unit 
} 
weak var tenant: Person? 
   deinit { print("Apartment \(unit) is being deinitialized") 
   }
 }
class CreditCard {
  let number: UInt64 unowned 
   let customer: Customer init(number: UInt64, customer: Customer) { 
    self.number = number self.customer = customer 
} 
  deinit {
     print("Card #\(number) is being deinitialized") 
  }
}```
###4、创建一个自动释放池(Autorelease Pool)

在 Objective - C 框架链接的应用程序,通常在它们的每一个线程必须创建至少 一个自动释放池。如果应用程序使用管理模型,即应用程序处理的 retain 和 release 对象,那么自动释放池捕获任何从该线程 autorelease 的对象。在Swift框架下呢??最近在Spritekit下做了一个Swift的demo。然后为了加载时高效一点,在子线程中加载背景,结果发现内存永远的增涨,以0.2MB,0.2MB的固定速度增涨,
[http://code4app.com/ios/569d055ab5ad2eba268b47f9](http://code4app.com/ios/569d055ab5ad2eba268b47f9)
排查最后,发现刚好背景图片切片的大小是0.2MB。这样的话,想来是没有别的原因了。我已经按照,正常的逻辑,在画面离开屏幕时就删除节点了,但是内存仍然在增加。想来也是没有其他原因。 在Swift中,子线程的内存仍然需要添加自动释放池,结果Swift开发指南中,并没有提到。
不过还是在Swifter中找到了,我想要的。
在 Swift 中我们也是能使用 autoreleasepool 的 -- 虽然语法上略有不同。相比于原来在 Objective-C 中的关键字,现在它变成了一个接受闭包的方法:
>func autoreleasepool(code: () -> ())

利用尾随闭包的写法,很容易就能在 Swift 中加入一个类似的自动释放池了:
>func loadBigData() 
{ 
  if let path = NSBundle.mainBundle() .pathForResource("big", ofType: "jpg")
  {
   for i in 1...10000 {
   autoreleasepool {
    let data = NSData.dataWithContentsOfFile( path, options: nil, error: nil) 
   NSThread.sleepForTimeInterval(0.5)
    }
   }
  }
}

这样改动以后。果然程序变得舒服多了。

相关文章

  • 每天学一点Swift----面向对象下(十)

    十九. Swift内存管理 1. Swift提供了强大的内存管理机制:Swift通过自动引用计数(ARC)可以很好...

  • 【Swift概念】Swift的内存管理

    Swift的内存管理怎么办?? 在Objective-C中无论ARC、MRC,开发中我们还是需要对内存进行管理,主...

  • Swift--内存管理

    Swift内存管理概述 强引用循环 打破强引用循环 闭包中的强引用循环 Swift内存管理概述 Swift中的AR...

  • Swift 内存管理

    Swift 内存管理 [TOC] 前言 本文将介绍一下Swift中的内存管理,关于内存的一些基础知识可以参考我以前...

  • Swift底层原理-内存管理

    Swift底层原理-内存管理 Swift语言延续了和Objective-C语言一样的思路进行内存管理,都是采用引用...

  • swift内存管理

    Swift使用自动引用计数(ARC)机制来处理内存。通常情况下,Swift内存管理机制会自动管理内存,无须我们考虑...

  • Swift使用自动引用计数

    Swift使用自动引用计数(ARC)机制来处理内存。通常情况下,Swift内存管理机制会自动管理内存,无须我们考虑...

  • Swift-内存管理,指针

    内存管理 Swift采用引用计数的ARC内存管理方案(堆空间) Swift的ARC中有3钟引用强引用弱引用(wea...

  • Swift内存管理&闭包使用

    一、内存管理 1、跟OC一样,Swift也是采取基于引用计数的ARC内存管理方案(针对堆空间) 2、Swift的A...

  • 内存管理

    内存管理 跟OC一样,Swift也是采取基于引用计数的ARC内存管理方案(针对堆空间) Swift的ARC中有3种...

网友评论

    本文标题:【Swift概念】Swift的内存管理

    本文链接:https://www.haomeiwen.com/subject/byjlkttx.html