Swift 自己主动引用计数机制ARC

Swift 使用自己主动引用计数(ARC)这一机制来跟踪和管理你的应用程序的内存。通常情况下,Swift 的内存管理机制会一直起着作用,你无须自己来考虑内存的管理。ARC 会在类的实例不再被使用时,自己主动释放其占用的内存。

然而,在少数情况下,ARC 为了能帮助你管理内存,须要很多其它的关于你的代码之间关系的信息。本章描写叙述了这些情况。而且为你示范如何启用 ARC 来管理你的应用程序的内存。

注意:

引用计数只应用于类的实例。结构体和枚举类型是值类型,不是引用类型,也不是通过引用的方式存储和传递。

自己主动引用计数的工作机制

当你每次创建一个类的新的实例的时候,ARC 会分配一大块内存用来储存实例的信息。内存中会包括实例的类型信息。以及这个实例全部相关属性的值。此外,当实例不再被使用时。ARC 释放实例所占用的内存,并让释放的内存能挪作他用。

这确保了不再被使用的实例,不会一直占用内存空间。

然而。当 ARC 收回和释放了正在被使用中的实例。该实例的属性和方法将不能再被訪问和调用。实际上,假设你试图訪问这个实例,你的应用程序非常可能会崩溃。

为了确保使用中的实例不会被销毁。ARC 会跟踪和计算每个实例正在被多少属性。常量和变量所引用。

哪怕实例的引用数为一,ARC都不会销毁这个实例。

为了使之成为可能,不管你将实例赋值给属性,常量或者是变量。属性,常量或者变量,都会对此实例创建强引用。

之所以称之为强引用。是由于它会将实例牢牢的保持住,仅仅要强引用还在,实例是不同意被销毁的。

 

自己主动引用计数实战

以下的样例展示了自己主动引用计数的工作机制。

样例以一个简单的Person类開始,并定义了一个叫name的常量属性:

  class Person {
       let name: String

            init(name: String) {
           self.name = name
           println("\(name) is being initialized")
       }

           deinit {
           println("\(name) is being deinitialized")
       }
    }

Person类有一个构造函数,此构造函数为实例的name属性赋值并打印出信息。以表明初始化过程生效。Person类同一时候也拥有析构函数,相同会在实例被销毁的时候打印出信息。

接下来的代码片段定义了三个类型为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实例不会被销毁:

reference2 = reference1
reference3 = reference1

ARC 会在第三个,也即最后一个强引用被断开的时候。销毁Person实例。这也意味着你不再使用这个Person实例:

reference3 = nil
// prints "John Appleseed is beingdeinitialized"

类实例之间的循环强引用

在上面的样例中,ARC 会跟踪你所新创建的Person实例的引用数量,而且会在Person实例不再被须要时销毁它。

然而。我们可能会写出这种代码,一个类永远不会有0个强引用。

这种情况发生在两个类实例互相保持对方的强引用。并让对方不被销毁。这就是所谓的循环强引用。

你能够通过定义类之间的关系为弱引用或者无主引用。以此替代强引用,从而解决循环强引用的问题。详细的过程在解决类实例之间的循环强引用中有描写叙述。无论如何。在你学习如何解决循环强引用之前,非常有必要了解一下它是如何产生的。

以下展示了一个不经意产生循环强引用的样例。

样例定义了两个类:Person和Apartment,用来建模公寓和它当中的居民:

class Person {
   let name: String
   init(name: String) { self.name = name }
   var apartment: Apartment?
   deinit { println("\(name) is being deinitialized") }
}

class Apartment {
   let number: Int
   init(number: Int) { self.number = number }
   var tenant: Person?
   deinit { println("Apartment #\(number) is beingdeinitialized") }
}

每个Person实例有一个类型为String,名字为name的属性,并有一个可选的初始化为nil的apartment属性。apartment属性是可选的,由于一个人并不总是拥有公寓。

类似的,每一个Apartment实例有一个叫number,类型为Int的属性,并有一个可选的初始化为nil的tenant属性。tenant属性是可选的,由于一栋公寓并不总是有居民。

这两个类都定义了析构函数。用以在类实例被析构的时候输出信息。这让你可以知晓Person和Apartment的实例是否像预期的那样被销毁。

接下来的代码片段定义了两个可选类型的变量john和number73,并分别被设定为以下的Apartment和Person的实例。这两个变量都被初始化为nil,并为可选的:

var john: Person?

var number73: Apartment?

如今你能够创建特定的Person和Apartment实例并将类实例赋值给john和number73变量:

john = Person(name: "JohnAppleseed")
number73 = Apartment(number: 73)

在两个实例被创建和赋值后。下图表面了强引用的关系。变量john如今有一个指向Person实例的强引用,而变量number73有一个指向Apartment实例的强引用:

如今你可以将这两个实例关联在一起。这样人就能有公寓住了,而公寓也有了房客。

注意感叹号是用来展开和訪问可选变量john和number73中的实例,这样实例的属性才干被赋值:

john!.apartment = number73
number73!.tenant = john

在将两个实例联系在一起之后。强引用的关系如图所看到的:

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvenBmODg2MQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" >

不幸的是。将这两个实例关联在一起之后,一个循环强引用被创建了。

Person实比如今有了一个指向Apartment实例的强引用。而Apartment实例也有了一个指向Person实例的强引用。

因此,当你断开john和number73变量所持有的强引用时,引用计数并不会降为 0,实例也不会被 ARC 销毁:

john = nil
number73 = nil

注意,当你把这两个变量设为nil时,没有不论什么一个析构函数被调用。强引用循环阻止了Person和Apartment类实例的销毁,并在你的应用程序中造成了内存泄漏。

在你将john和number73赋值为nil后,强引用关系例如以下图:

Person和Apartment实例之间的强引用关系保留了下来而且不会被断开。

解决实例之间的循环强引用

Swift 提供了两种办法用来解决你在使用类的属性时所遇到的循环强引用问题:弱引用(weak reference)和无主引用(unowned reference)。

弱引用和无主引用同意循环引用中的一个实例引用另外一个实例而不保持强引用。这样实例可以互相引用而不产生循环强引用。

对于生命周期中会变为nil的实例使用弱引用。相反的。对于初始化赋值后再也不会被赋值为nil的实例,使用无主引用。

弱引用

弱引用不会牢牢保持住引用的实例,而且不会阻止 ARC 销毁被引用的实例。这样的行为阻止了引用变为循环强引用。声明属性或者变量时,在前面加上weakkeyword表明这是一个弱引用。

在实例的生命周期中。假设某些时候引用没有值,那么弱引用能够阻止循环强引用。假设引用总是有值,则能够使用无主引用,在无主引用中有描写叙述。

在上面Apartment的样例中,一个公寓的生命周期中,有时是没有“居民”的,因此适合使用弱引用来解决循环强引用。

注意:

弱引用必须被声明为变量,表明其值能在执行时被改动。弱引用不能被声明为常量。

由于弱引用能够没有值,你必须将每个弱引用声明为可选类型。

可选类型是在 Swift 语言中推荐的用来表示可能没有值的类型。

由于弱引用不会保持所引用的实例,即使引用存在。实例也有可能被销毁。因此。ARC 会在引用的实例被销毁后自己主动将其赋值为nil。你能够像其它可选值一样,检查弱引用的值是否存在,你永远也不会遇到被销毁了而不存在的实例。

以下的样例跟上面Person和Apartment的样例一致。可是有一个重要的差别。

这一次,Apartment的tenant属性被声明为弱引用:

class Person {
   let name: String
   init(name: String) { self.name = name }
   var apartment: Apartment?
   deinit { println("\(name) is being deinitialized") }
}

class Apartment {
   let number: Int
   init(number: Int) { self.number = number }
   weak var tenant: Person?

deinit { println("Apartment #\(number) is beingdeinitialized") }
}

然后跟之前一样,建立两个变量(john和number73)之间的强引用,并关联两个实例:

var john: Person?

var number73: Apartment?

john = Person(name: "JohnAppleseed")
number73 = Apartment(number: 73)

john!.apartment = number73
number73!.tenant = john

如今,两个关联在一起的实例的引用关系例如以下图所看到的:

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvenBmODg2MQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" >

Person实例依旧保持对Apartment实例的强引用,可是Apartment实例仅仅是对Person实例的弱引用。

这意味着当你断开john变量所保持的强引用时,再也没有指向Person实例的强引用了:

因为再也没有指向Person实例的强引用,该实例会被销毁:

john = nil
// prints "John Appleseed is beingdeinitialized"

唯一剩下的指向Apartment实例的强引用来自于变量number73。

假设你断开这个强引用,再也没有指向Apartment实例的强引用了:

因为再也没有指向Apartment实例的强引用,该实例也会被销毁:

number73 = nil
// prints "Apartment #73 is beingdeinitialized"

上面的两段代码展示了变量john和number73在被赋值为nil后。Person实例和Apartment实例的析构函数都打印出“销毁”的信息。

这证明了引用循环被打破了。

无主引用

和弱引用类似,无主引用不会牢牢保持住引用的实例。和弱引用不同的是,无主引用是永远有值的。因此。无主引用总是被定义为非可选类型(non-optional type)。

你能够在声明属性或者变量时,在前面加上keywordunowned表示这是一个无主引用。

由于无主引用是非可选类型,你不须要在使用它的时候将它展开。

无主引用总是能够被直接訪问。

只是 ARC 无法在实例被销毁后将无主引用设为nil,由于非可选类型的变量不同意被赋值为nil。

注意: 假设你试图在实例被销毁后,訪问该实例的无主引用。会触发执行时错误。使用无主引用,你必须确保引用始终指向一个未销毁的实例。

还须要注意的是假设你试图訪问实例已经被销毁的无主引用,程序会直接崩溃。而不会发生无法预期的行为。

所以你应当避免这种事情发生。

以下的样例定义了两个类,Customer和CreditCard,模拟了银行客户和客户的信用卡。

这两个类中,每个都将另外一个类的实例作为自身的属性。

这样的关系会潜在的创造循环强引用。

Customer和CreditCard之间的关系与前面弱引用样例中Apartment和Person的关系截然不同。

在这个数据模型中。一个客户可能有或者没有信用卡,可是一张信用卡总是关联着一个客户。为了表示这样的关系。Customer类有一个可选类型的card属性。可是CreditCard类有一个非可选类型的customer属性。

此外,仅仅能通过将一个number值和customer实例传递给CreditCard构造函数的方式来创建CreditCard实例。这样能够确保当创建CreditCard实例时总是有一个customer实例与之关联。

因为信用卡总是关联着一个客户。因此将customer属性定义为无主引用,用以避免循环强引用:

class Customer {
   let name: String
   var card: CreditCard?
   init(name: String) {
       self.name = name
    }
   deinit { println("\(name) is being deinitialized") }
}

class CreditCard {
   let number: Int
   unowned let customer: Customer
   init(number: Int, customer: Customer) {
       self.number = number
       self.customer = customer
    }
   deinit { println("Card #\(number) is being deinitialized") }
}

以下的代码片段定义了一个叫john的可选类型Customer变量,用来保存某个特定客户的引用。因为是可选类型。所以变量被初始化为nil。

var john: Customer?

如今你能够创建Customer类的实例,用它初始化CreditCard实例。并将新创建的CreditCard实例赋值为客户的card属性。

john = Customer(name: "JohnAppleseed")
john!.card = CreditCard(number:1234_5678_9012_3456, customer: john!)

在你关联两个实例后,他们的引用关系例如以下图所看到的:

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvenBmODg2MQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" >

Customer实例持有对CreditCard实例的强引用,而CreditCard实例持有对Customer实例的无主引用。

因为customer的无主引用,当你断开john变量持有的强引用时,再也没有指向Customer实例的强引用了:

因为再也没有指向Customer实例的强引用,该实例被销毁了。

其后,再也没有指向CreditCard实例的强引用,该实例也随之被销毁了:

john = nil
// prints "John Appleseed is beingdeinitialized"
// prints "Card #1234567890123456 isbeing deinitialized"

最后的代码展示了在john变量被设为nil后Customer实例和CreditCard实例的构造函数都打印出了“销毁”的信息。

无主引用以及显式展开的可选属性

上面弱引用和无主引用的样例涵盖了两种经常使用的须要打破循环强引用的场景。

Person和Apartment的样例展示了两个属性的值都同意为nil。并会潜在的产生循环强引用。这样的场景最适合用弱引用来解决。

Customer和CreditCard的样例展示了一个属性的值同意为nil。而还有一个属性的值不同意为nil,并会潜在的产生循环强引用。这样的场景最适合通过无主引用来解决。

然而,存在着第三种场景,在这样的场景中。两个属性都必须有值,而且初始化完毕后不能为nil。

在这样的场景中,须要一个类使用无主属性,而另外一个类使用显示展开的可选属性。

这使两个属性在初始化完毕后能被直接訪问(不须要可选展开),同一时候避免了循环引用。

这一节将为你展示怎样建立这样的关系。

以下的样例定义了两个类,Country和City,每一个类将另外一个类的实例保存为属性。在这个模型中。每一个国家必须有首都。而每一个城市必须属于一个国家。为了实现这样的关系。Country类拥有一个capitalCity属性。而City类有一个country属性:

class Country {
   let name: String
   let capitalCity: City!
   init(name: String, capitalName: String) {
       self.name = name
       self.capitalCity = City(name: capitalName, country: self)
    }
}

class City {
   let name: String
   unowned let country: Country
   init(name: String, country: Country) {
       self.name = name
       self.country = country
    }
}

为了建立两个类的依赖关系,City的构造函数有一个Country实例的參数,而且将实例保存为country属性。

Country的构造函数调用了City的构造函数。

然而。仅仅有Country的实例全然初始化完后,Country的构造函数才干把self传给City的构造函数。(在两步构造函数中有详细描写叙述)

为了满足这样的需求。通过在类型结尾处加上感叹号(City!)的方式,将Country的capitalCity属性声明为显示展开的可选类型属性。这表示像其它可选类型一样,capitalCity属性的默认值为nil,可是不须要展开他的值就能訪问它。

(在显示展开的可选类型中有描写叙述)

因为capitalCity默认值为nil,一旦Country的实例在构造函数中给name属性赋值后,整个初始化过程就完毕了。这代表一旦name属性被后,Country的构造函数就能引用并传递显式的self。Country的构造函数在赋值capitalCity时,就能将self作为參数传递给City的构造函数。

以上的意义在于你能够通过一条语句同一时候创建Country和City的实例,而不产生循环强引用。而且capitalCity的属性能被直接訪问,而不须要通过感叹号来展开它的可选值:

var country = Country(name:"Canada", capitalName: "Ottawa")
println("\(country.name)'s capitalcity is called \(country.capitalCity.name)")
// prints "Canada's capital city iscalled Ottawa"

在上面的样例中,使用显示展开可选值的意义在于满足了两个类构造函数的需求。

capitalCity属性在初始化完毕后。能作为非可选值使用同事还避免了循环强引用。

闭包引起的循环强引用

前面我们看到了循环强引用环是在两个类实例属性互相保持对方的强引用时产生的。还知道了怎样用弱引用和无主引用来打破循环强引用。

循环强引用还会发生在当你将一个闭包赋值给类实例的某个属性,而且这个闭包体中又使用了实例。

这个闭包体中可能訪问了实例的某个属性,比如self.someProperty,或者闭包中调用了实例的某个方法,比如self.someMethod。

这两种情况都导致了闭包“捕获" self。从而产生了循环强引用。

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

Swift 提供了一种优雅的方法来解决问题,称之为闭包占用列表(closuer capture list)。相同的。在学习怎样用闭包占用列表破坏循环强引用之前,先来了解一下循环强引用是怎样产生的,这对我们是非常有帮助的。

以下的样例为你展示了当一个闭包引用了self后是怎样产生一个循环强引用的。样例中定义了一个叫HTMLElement的类。用一种简单的模型表示 HTML 中的一个单独的元素:

class HTMLElement {

   let name: String
   let text: String?

@lazy var asHTML: () -> String = {
       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 {
       println("\(name) is being deinitialized")
    }

}

HTMLElement类定义了一个name属性来表示这个元素的名称。比如代表段落的"p",或者代表换行的"br"。HTMLElement还定义了一个可选属性text。用来设置和展现 HTML 元素的文本。

除了上面的两个属性,HTMLElement还定义了一个lazy属性asHTML。这个属性引用了一个闭包,将name和text组合成 HTML 字符串片段。该属性是() -> String类型,或者能够理解为“一个没有參数。返回String的函数”。

默认情况下。闭包赋值给了asHTML属性,这个闭包返回一个代表 HTML 标签的字符串。假设text值存在,该标签就包括可选值text。假设text不存在,该标签就不包括文本。

对于段落元素,依据text是"some text"还是nil,闭包会返回"<p>some text</p>"或者"<p/>"。

能够像实例方法那样去命名、使用asHTML属性。

然而。因为asHTML是闭包而不是实例方法,假设你想改变特定元素的 HTML 处理的话,能够用自己定义的闭包来代替默认值。

注意:

asHTML声明为lazy属性,由于仅仅有当元素确实须要处理为HTML输出的字符串时。才须要使用asHTML。也就是说,在默认的闭包中能够使用self,由于仅仅有当初始化完毕以及self确实存在后。才干訪问lazy属性。

HTMLElement类仅仅提供一个构造函数,通过name和text(假设有的话)參数来初始化一个元素。该类也定义了一个析构函数,当HTMLElement实例被销毁时。打印一条消息。

以下的代码展示了怎样用HTMLElement类创建实例并打印消息。

var paragraph: HTMLElement?

=HTMLElement(name: "p", text: "hello, world")
println(paragraph!.asHTML())
// prints"hello, world"

注意:

上面的paragraph变量定义为可选HTMLElement。因此我们能够赋值nil给它来演示循环强引用。

不幸的是,上面写的HTMLElement类产生了类实例和asHTML默认值的闭包之间的循环强引用。

循环强引用例如以下图所看到的:

实例的asHTML属性持有闭包的强引用。可是。闭包在其闭包体内使用了self(引用了self.name和self.text),因此闭包占有了self,这意味着闭包又反过来持有了HTMLElement实例的强引用。这样两个对象就产生了循环强引用。(很多其它关于闭包占有值的信息。请參考值捕获)。

注意:

尽管闭包多次使用了self,它仅仅占有HTMLElement实例的一个强引用。

假设设置paragraph变量为nil,打破它持有的HTMLElement实例的强引用,HTMLElement实例和它的闭包都不会被销毁。也是由于循环强引用:

paragraph = nil

注意HTMLElementdeinitializer中的消息并没有别打印,证明了HTMLElement实例并没有被销毁。

解决闭包引起的循环强引用

在定义闭包时同一时候定义占有列表作为闭包的一部分,通过这样的方式能够解决闭包和类实例之间的循环强引用。

占有列表定义了闭包体内占有一个或者多个引用类型的规则。

跟解决两个类实例间的循环强引用一样,声明每一个占有的引用为弱引用或无主引用。而不是强引用。应当依据代码关系来决定使用弱引用还是无主引用。

注意:

Swift 有例如以下要求:仅仅要在闭包内使用self的成员,就要用self.someProperty或者self.someMethod(而不仅仅是someProperty或someMethod)。这提醒你可能会不小心就占有了self。

定义占有列表

占有列表中的每一个元素都是由weak或者unownedkeyword和实例的引用(如self或someInstance)成对组成。每一对都在花括号里,通过逗号分开。

占有列表放置在闭包參数列表和返回类型之前:

@lazy var someClosure: (Int, String) ->String = {
   [unowned self] (index: Int, stringToProcess: String) -> String in
   // closure body goes here
}

假设闭包没有指定參数列表或者返回类型,则能够通过上下文判断,那么能够占有列表放在闭包開始的地方,跟着是keywordin:

@lazy var someClosure: () -> String = {
   [unowned self] in
   // closure body goes here
}

弱引用和无主引用

当闭包和占有的实例总是互相引用时而且总是同一时候销毁时。将闭包内的占有定义为无主引用。

相反的,当占有引用有时可能会是nil时,将闭包内的占有定义为弱引用。弱引用总是可选类型。而且当引用的实例被销毁后。弱引用的值会自己主动置为nil。这使我们能够在闭包内检查他们是否存在。

注意:

假设占有的引用绝对不会置为nil,应该用无主引用,而不是弱引用。

前面的HTMLElement样例中。无主引用是正确的解决循环强引用的方法。

这样这样编写HTMLElement类来避免循环强引用:

class HTMLElement {

   let name: String
   let text: String?

   @lazy var asHTML: () -> String = {
       [unowned self] in
       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 {
       println("\(name) is being deinitialized")
    }

}

上面的HTMLElement实现和之前的实现一致,仅仅是在asHTML闭包中多了一个占有列表。这里。占有列表是[unowned self],表示“用无主引用而不是强引用来占有self”。

和之前一样,我们能够创建并打印HTMLElement实例:

v

ar paragraph: HTMLElement? =HTMLElement(name: "p", text: "hello, world")
println(paragraph!.asHTML())
// prints "<p>hello,world</p>"

使用占有列表后引用关系例如以下图所看到的:

这一次,闭包以无主引用的形式占有self,并不会持有HTMLElement实例的强引用。

假设将paragraph赋值为nil,HTMLElement实例将会被销毁。并能看到它的析构函数打印出的消息。

paragraph = nil
// prints "p is beingdeinitialized"
时间: 2024-10-13 04:42:58

Swift 自己主动引用计数机制ARC的相关文章

Swift 自动引用计数机制ARC

Swift 使用自动引用计数(ARC)这一机制来跟踪和管理你的应用程序的内存.通常情况下,Swift 的内存管理机制会一直起着作用,你无须自己来考虑内存的管理.ARC 会在类的实例不再被使用时,自动释放其占用的内存. 然而,在少数情况下,ARC 为了能帮助你管理内存,需要更多的关于你的代码之间关系的信息.本章描述了这些情况,并且为你示范怎样启用 ARC 来管理你的应用程序的内存. 注意: 引用计数仅仅应用于类的实例.结构体和枚举类型是值类型,不是引用类型,也不是通过引用的方式存储和传递. 自动引

初步swift语言学习笔记6(ARC-自己主动引用计数,内存管理)

笔者:fengsh998 原文地址:http://blog.csdn.net/fengsh998/article/details/31824179 转载请注明出处 假设认为文章对你有所帮助.请通过留言或关注微信公众帐号fengsh998来支持我,谢谢. Swift使用自己主动引用计数(ARC)来管理应用程序的内存使用.这表示内存管理已经是Swift的一部分,在大多数情况下,你并不须要考虑内存的管理. 当实例并不再被须要时.ARC会自己主动释放这些实例所使用的内存. 另外须要注意的: 引用计数仅仅

Swift的自动引用计数

前言 在iOS5之后apple推出了相对于MRC(Mannul Reference Counting)的ARC(Automatic Reference Counting)的内存管理机制,前者是对内存的手动管理,后者是系统对内存的智能化管理.其实我学习iOS的时候已经推出到iOS7了,对于MRC机制我甚至连一知半解都算不上.有时候和iOS老司机交流的时候他们对于各种内存都很熟悉,感觉包括我在内的很多最近两年刚学习iOS开发的同学,都属于填鸭式的学习吧,知其然不知其所以然,甚至都没耐心去读优秀的源码

swift:自动引用计数ARC

Swift自动引用计数:ARC Swift使用自动引用计数(ARC)来跟踪并管理应用使用的内存.大部分情况下,这意味着在Swift语言中,内存管理"仍然工作",不需要自己去考虑内存管理的事情.当实例不再被使用时,ARC会自动释放这些类的实例所占用的内存. 然而,在少数情况下,为了自动的管理内存空间,ARC需要了解关于你的代码片段之间关系的更多信息.本章描述了这些情况,并向大家展示如何打开ARC来管理应用的所有内存空间. 注意:引用计数只应用在类的实例.结构体(Structure)和枚举

swift学习笔记(七)自己主动引用计数

与Object-c一样,swift使用自己主动引用计数来跟踪并管理应用使用的内存.当实例不再被使用时,及retainCount=0时,会自己主动释放是理所占用的内存空间. 注:引用计数仅适用于类的实例,由于struct和enumeration属于值类型,也就不牵涉引用,所以其存储和管理方式并非引用计数. 当一个实例被初始化时,系统会自己主动分配一定的内存空间,用于管理属性和方法.当实例对象不再被使用时,其内存空间被收回. swift中的引用类型分为三种,即Strong强引用,weak弱引用和无主

第九讲.内存管理初级.(内存管理的方式,引用计数机制及影响计数的各个方法,dealloc方法,内存管理的基本原则,掌握copy的实现)

一.内存管理的方式. 1.进行内存管理的原因: 1>.由于移动设备的内存极其有限,所以每个APP所占的内存也是有限制的,当app所占用的内存较多时,系统就会发出内存警告,这时需要回收一些不需要再继续使用的内存空间,比如回收一些不再使用的对象和变量等. 管理范围:任何继承NSObject的对象,对其他的基本数据类型无效. 2>.本质原因是因为对象和其他数据类型在系统中的存储空间不一样,其它局部变量主要存放于栈中,而对象存储于堆中,当代码块结束时这个代码块中涉及的所有局部变量会被回收,指向对象的指

opencv笔记(一)——Mat的引用计数机制

Mat是Opencv2里面主要的类.Mat的对象常常用来表示一副图像的信息. Mat的基本操作十分简单,不多说了.下面这段代码能够读七八分明白,应该就算对Mat有大体了解. 1 /* For description look into the help() function. */ 2 3 #include "opencv2/core/core.hpp" 4 #include <iostream> 5 6 using namespace std; 7 using names

深入理解 PHP7 中全新的 zval 容器和引用计数机制

深入理解 PHP7 中全新的 zval 容器和引用计数机制 最近在查阅 PHP7 垃圾回收的资料的时候,网上的一些代码示例在本地环境下运行时出现了不同的结果,使我一度非常迷惑. 仔细一想不难发现问题所在:这些文章大多是 PHP5.x 时代的,而 PHP7 发布后,采用了新的 zval 结构,相关的资料也比较贫瘠,所以我结合一些资料做了一个总结, 主要侧重于解释新 zval 容器中的引用计数机制 ,如有谬误,还望不吝指教. PHP7 中新的 zval 结构 明人不说暗话,先看代码! struct 

iOS内存管理机制解析之MRC手动引用计数机制

前言: iOS的内存管理机制ARC和MRC是程序员参加面试基本必问的问题,也是考察一个iOS基本功是 否扎实的关键,这样深入理解内存管理机制的重要性就不言而喻了. iOS内存管理机制发展史 iOS 5以前 :MRC(手动引用计数) iOS 5及以后:ARC (自动引入计数) MRC机制时代 "谁开辟申请,谁及时合理释放" 面对自己申请的内存空间是要及时进行回收的: 不及时释放会造成什么结果? 对象存储在栈上,可能会大量的占用内存,内存不足造成程序闪退(也就是所说的内存泄露) 不合理释放