日本综合一区二区|亚洲中文天堂综合|日韩欧美自拍一区|男女精品天堂一区|欧美自拍第6页亚洲成人精品一区|亚洲黄色天堂一区二区成人|超碰91偷拍第一页|日韩av夜夜嗨中文字幕|久久蜜综合视频官网|精美人妻一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問(wèn)題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷解決方案
講解一下Swift變量

Swift采用現(xiàn)代編程模式,避免了一些常見(jiàn)的編程錯(cuò)誤。

  • 變量先初始化,再使用;
  • 數(shù)組下標(biāo)會(huì)進(jìn)行校驗(yàn),避免溢出;
  • 整型進(jìn)行校驗(yàn),避免溢出;
  • 可選(Optional)類型,確保了缺失值nil被精確使用;
  • 內(nèi)存自動(dòng)管理;
  • 錯(cuò)誤處理機(jī)制,更好地從無(wú)法預(yù)計(jì)的錯(cuò)誤中恢復(fù);

Swift 使用自動(dòng)引用計(jì)數(shù)(ARC)這一機(jī)制來(lái)跟蹤和管理應(yīng)用程序的內(nèi)存

通常情況下我們不需要去手動(dòng)釋放內(nèi)存,因?yàn)?ARC 會(huì)在類的實(shí)例不再被使用時(shí),自動(dòng)釋放其占用的內(nèi)存。

但在有些時(shí)候我們還是需要在代碼中實(shí)現(xiàn)內(nèi)存管理。

ARC 功能

1.當(dāng)每次使用 init() 方法創(chuàng)建一個(gè)類的新的實(shí)例的時(shí)候,ARC 會(huì)分配一大塊內(nèi)存用來(lái)儲(chǔ)存實(shí)例的信息。 2.內(nèi)存中會(huì)包含實(shí)例的類型信息,以及這個(gè)實(shí)例所有相關(guān)屬性的值。 3.當(dāng)實(shí)例不再被使用時(shí),ARC 釋放實(shí)例所占用的內(nèi)存,并讓釋放的內(nèi)存能挪作他用。 4.為了確保使用中的實(shí)例不會(huì)被銷毀,ARC 會(huì)跟蹤和計(jì)算每一個(gè)實(shí)例正在被多少屬性,常量和變量所引用。 5.實(shí)例賦值給屬性、常量或變量,它們都會(huì)創(chuàng)建此實(shí)例的強(qiáng)引用,只要強(qiáng)引用還在,實(shí)例是不允許被銷毀的。

ARC 實(shí)例

class Person {
   let name: String
   init(name: String) {
       self.name = name
       print("\(name) 開(kāi)始初始化")
   }
   deinit {
       print("\(name) 被析構(gòu)")
   }
}

// 值會(huì)被自動(dòng)初始化為nil,目前還不會(huì)引用到Person類的實(shí)例
var reference1: Person?
var reference2: Person?
var reference3: Person?

// 創(chuàng)建Person類的新實(shí)例
reference1 = Person(name: "Runoob")


//賦值給其他兩個(gè)變量,該實(shí)例又會(huì)多出兩個(gè)強(qiáng)引用
reference2 = reference1
reference3 = reference1

//斷開(kāi)第一個(gè)強(qiáng)引用
reference1 = nil
//斷開(kāi)第二個(gè)強(qiáng)引用
reference2 = nil
//斷開(kāi)第三個(gè)強(qiáng)引用,并調(diào)用析構(gòu)函數(shù)
reference3 = nil

以上程序執(zhí)行輸出結(jié)果為:

Runoob 開(kāi)始初始化
Runoob 被析構(gòu)

類實(shí)例之間的循環(huán)強(qiáng)引用

在上面的例子中,ARC 會(huì)跟蹤你所新創(chuàng)建的 Person 實(shí)例的引用數(shù)量,并且會(huì)在 Person 實(shí)例不再被需要時(shí)銷毀它。 然而,我們可能會(huì)寫出這樣的代碼,一個(gè)類永遠(yuǎn)不會(huì)有0個(gè)強(qiáng)引用。這種情況發(fā)生在兩個(gè)類實(shí)例互相保持對(duì)方的強(qiáng)引用,并讓對(duì)方不被銷毀。這就是所謂的循環(huán)強(qiáng)引用。

實(shí)例

下面展示了一個(gè)不經(jīng)意產(chǎn)生循環(huán)強(qiáng)引用的例子。例子定義了兩個(gè)類:Person和Apartment,用來(lái)建模公寓和它其中的居民:

class Person {
   let name: String
   init(name: String) { self.name = name }
   var apartment: Apartment?
   deinit { print("\(name) 被析構(gòu)") }
}

class Apartment {
   let number: Int
   init(number: Int) { self.number = number }
   var tenant: Person?
   deinit { print("Apartment #\(number) 被析構(gòu)") }
}

// 兩個(gè)變量都被初始化為nil
var runoob: Person?
var number73: Apartment?

// 賦值
runoob = Person(name: "Runoob")
number73 = Apartment(number: 73)

// 意感嘆號(hào)是用來(lái)展開(kāi)和訪問(wèn)可選變量 runoob 和 number73 中的實(shí)例
// 循環(huán)強(qiáng)引用被創(chuàng)建
runoob!.apartment = number73
number73!.tenant = runoob

// 斷開(kāi) runoob 和 number73 變量所持有的強(qiáng)引用時(shí),引用計(jì)數(shù)并不會(huì)降為 0,實(shí)例也不會(huì)被 ARC 銷毀
// 注意,當(dāng)你把這兩個(gè)變量設(shè)為nil時(shí),沒(méi)有任何一個(gè)析構(gòu)函數(shù)被調(diào)用。
// 強(qiáng)引用循環(huán)阻止了Person和Apartment類實(shí)例的銷毀,并在你的應(yīng)用程序中造成了內(nèi)存泄漏
runoob = nil
number73 = nil

解決實(shí)例之間的循環(huán)強(qiáng)引用

Swift 提供了兩種辦法用來(lái)解決你在使用類的屬性時(shí)所遇到的循環(huán)強(qiáng)引用問(wèn)題: 1.弱引用 2.無(wú)主引用 弱引用和無(wú)主引用允許循環(huán)引用中的一個(gè)實(shí)例引用另外一個(gè)實(shí)例而不保持強(qiáng)引用。這樣實(shí)例能夠互相引用而不產(chǎn)生循環(huán)強(qiáng)引用。 對(duì)于生命周期中會(huì)變?yōu)閚il的實(shí)例使用弱引用。相反的,對(duì)于初始化賦值后再也不會(huì)被賦值為nil的實(shí)例,使用無(wú)主引用。

弱引用實(shí)例

class Module {
   let name: String
   init(name: String) { self.name = name }
   var sub: SubModule?
   deinit { print("\(name) 主模塊") }
}

class SubModule {
   let number: Int
   
   init(number: Int) { self.number = number }
   
   weak var topic: Module?
   
   deinit { print("子模塊 topic 數(shù)為 \(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

以上程序執(zhí)行輸出結(jié)果為:

ARC 主模塊
子模塊 topic 數(shù)為 4

無(wú)主引用實(shí)例

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("學(xué)生的分?jǐn)?shù)為 \(marks)") }
}

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

以上程序執(zhí)行輸出結(jié)果為:

ARC
學(xué)生的分?jǐn)?shù)為 98

閉包引起的循環(huán)強(qiáng)引用

循環(huán)強(qiáng)引用還會(huì)發(fā)生在當(dāng)你將一個(gè)閉包賦值給類實(shí)例的某個(gè)屬性,并且這個(gè)閉包體中又使用了實(shí)例。這個(gè)閉包體中可能訪問(wèn)了實(shí)例的某個(gè)屬性,例如self.someProperty,或者閉包中調(diào)用了實(shí)例的某個(gè)方法,例如self.someMethod。這兩種情況都導(dǎo)致了閉包 “捕獲” self,從而產(chǎn)生了循環(huán)強(qiáng)引用。

實(shí)例

下面的例子為你展示了當(dāng)一個(gè)閉包引用了self后是如何產(chǎn)生一個(gè)循環(huán)強(qiáng)引用的。例子中定義了一個(gè)叫HTMLElement的類,用一種簡(jiǎn)單的模型表示 HTML 中的一個(gè)單獨(dú)的元素:

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

// 創(chuàng)建實(shí)例并打印信息
var paragraph: HTMLElement? = HTMLElement(name: "p", text: "hello, world")
print(paragraph!.asHTML())

HTMLElement 類產(chǎn)生了類實(shí)例和 asHTML 默認(rèn)值的閉包之間的循環(huán)強(qiáng)引用。

實(shí)例的 asHTML 屬性持有閉包的強(qiáng)引用。但是,閉包在其閉包體內(nèi)使用了self(引用了self.name和self.text),因此閉包捕獲了self,這意味著閉包又反過(guò)來(lái)持有了HTMLElement實(shí)例的強(qiáng)引用。這樣兩個(gè)對(duì)象就產(chǎn)生了循環(huán)強(qiáng)引用。

解決閉包引起的循環(huán)強(qiáng)引用:在定義閉包時(shí)同時(shí)定義捕獲列表作為閉包的一部分,通過(guò)這種方式可以解決閉包和類實(shí)例之間的循環(huán)強(qiáng)引用。

弱引用和無(wú)主引用

當(dāng)閉包和捕獲的實(shí)例總是互相引用時(shí)并且總是同時(shí)銷毀時(shí),將閉包內(nèi)的捕獲定義為無(wú)主引用。

相反的,當(dāng)捕獲引用有時(shí)可能會(huì)是nil時(shí),將閉包內(nèi)的捕獲定義為弱引用。

如果捕獲的引用絕對(duì)不會(huì)置為nil,應(yīng)該用無(wú)主引用,而不是弱引用。

實(shí)例

前面的HTMLElement例子中,無(wú)主引用是正確的解決循環(huán)強(qiáng)引用的方法。這樣編寫HTMLElement類來(lái)避免循環(huán)強(qiáng)引用:

class HTMLElement {
   
   let name: String
   let text: String?
   
   lazy var asHTML: () -> String = {
       [unowned self] in
       if let text = self.text {
           return "\(text)"
       } else {
           return ""
       }
   }
   
   init(name: String, text: String? = nil) {
       self.name = name
       self.text = text
   }
   
   deinit {
       print("\(name) 被析構(gòu)")
   }
   
}

//創(chuàng)建并打印HTMLElement實(shí)例
var paragraph: HTMLElement? = HTMLElement(name: "p", text: "hello, world")
print(paragraph!.asHTML())

// HTMLElement實(shí)例將會(huì)被銷毀,并能看到它的析構(gòu)函數(shù)打印出的消息
paragraph = nil

以上程序執(zhí)行輸出結(jié)果為:

hello, world
p 被析構(gòu)

分享名稱:講解一下Swift變量
文章鏈接:http://www.dlmjj.cn/article/dpigeic.html