Swift學習筆記 三十七 自動引用計數 下

2021-09-26 12:51:54 字數 4329 閱讀 1204

和弱引用類似,無主引用不會牢牢保持住引用的實例。和弱引用不同的是,⽆主引用在其他實例有相同或者更長的⽣命週期時使

⽤。你可以在宣告屬性或者變量時,在前面加上關鍵字 unowned 表示這是乙個⽆主引用。

⽆主引用通常都被期望擁有值。不過 arc 無法在實例被銷毀後將⽆主引用設為 nil ,因為非可選型別的變量不允許被賦值為 nil 。

使用無主引用,你必須確保引用始終指向乙個未銷毀的實例。如果你試圖在實例被銷毀後,訪問該實例的無主引用,會觸發運行時

錯誤。

下面的例子定義了兩個類, customer 和 creditcard ,模擬了銀⾏客戶和客戶的信用卡。這兩個類中,每乙個都將另外乙個類的

例項作為自身的屬性。這種關係可能會造成迴圈強引用。

customer 和 creditcard 之間的關係與前⾯弱引用例子中 apartment 和 person 的關係略微不同。在這個資料模型中,⼀個客戶

可能有或者沒有信用卡,但是一張信⽤卡總是關聯著乙個客戶。為了表示這種關係, customer 類有乙個可選型別的 card 屬性,

但是 creditcard 類有乙個非可選型別的 customer 屬性。

此外,只能通過將乙個 number 值和 customer 實例傳遞給 creditcard 構造器的方式來建立 creditcard 實例。這樣可以確保當創

建 creditcard 實例時總是有乙個 customer 實例與之關聯。

由於信⽤卡總是關聯著乙個客戶,因此將 customer 屬性定義為⽆主引用,⽤以避免迴圈強引用:

class customer

deinit

class creditcard

creditcard 類的 number 屬性被定義為 uint64 型別⽽不是 int 型別,以確保 number 屬性的儲存量在 32 位和 64 位系統上都能

足夠容納 16 位的卡號。

下⾯的**片段定義了乙個叫 john 的可選型別 customer 變量,用來儲存某個特定客戶的引用。由於是可選型別, 所以變量被

初始化為 nil :

var john: customer?

現在你可以建立 customer 類的實例,用它初始化 creditcard 實例,並將新建立的 creditcard 實例賦值為客戶的 card 屬性:

john!.card = creditcard(number: 1234_5678_9012_3456, customer: john!)

在你關聯兩個實例後,它們的引用關係如下圖所示:

customer 實例持有對 creditcard 實例的強引用,而 creditcard 實例持有對 customer 實例的無主引用。 由於 customer 的無主

引用,當你斷開 john 變量持有的強引用時,再也沒有指向 customer 實例的強引用了:

由於再也沒有指向 customer 實例的強引用,該例項被銷毀了。其後,再也沒有指向 creditcard 實例的強引用,該實例也隨之被

銷毀了:

john = nil

// 列印「card #1234567890123456 is being deinitialized」

最後的**展示了在 john 變量被設為 nil 後 customer 實例和 creditcard 實例的析構器都列印出了「銷 毀」的資訊。

上⾯的例子展示了如何使用安全的無主引用。對於需要禁用運⾏時的安全檢查的情況(例如,出於效能⽅面的原因),swift 還提

供了不安全的無主引用。與所有不安全的操作一樣,你需要負責檢查**以確保其安全性。 你可以通過 unowned(unsafe) 來聲

明不安全無主引用。如果你試圖在實例被銷毀後,訪問該實例的不安全無主引用,你的程式會嘗試訪問該實例之前所在的記憶體地

址,這是乙個不安全的操作。

上⾯弱引用和無主引⽤的例子涵蓋了兩種常用的需要打破迴圈強引用的場景。

person 和 apartment 的例子展示了兩個屬性的值都允許為 nil ,並會潛在的產生迴圈強引用。這種場景最適合用弱引用來解

決。

customer 和 creditcard 的例子展示了乙個屬性的值允許為 nil ,而另乙個屬性的值不允許為 nil ,這也可能會產生迴圈強引

⽤。這種場景最適合通過⽆主引用來解決。

然而,存在著第三種場景,在這種場景中,兩個屬性都必須有值,並且初始化完成後永遠不會為 nil 。在這種場景中, 需要乙個

類使⽤無主屬性,而另外乙個類使用隱式解包可選值屬性。

這使兩個屬性在初始化完成後能被直接訪問(不需要可選展開),同時避免了迴圈引用。這一節將為你展示如何建立這種關係。

下面的例子定義了兩個類, country 和 city ,每個類將另外乙個類的例項儲存為屬性。在這個模型中,每個國家必須有首都,每

個城市必須屬於乙個國家。為了實現這種關係, country 類擁有乙個 capitalcity 屬性,而 city 類有乙個 country 屬性:

class country else

htmlelement 類定義了乙個 name 屬性來表示這個元素的名稱,例如代表頭部元素的 "h1" ,代表段落的 "p" , 或者代表換行的 

"br" 。 htmlelement 還定義了乙個可選屬性 text ,用來設定 html 元素呈現的文字。

除了上⾯的兩個屬性, htmlelement 還定義了乙個 lazy 屬性 ashtml 。這個屬性引用了乙個將 name 和 text 組合成 html 字

符串片段的閉包。該屬性是 void -> string 型別,或者可以理解為「乙個沒有引數,返回string 的函式」。

預設情況下,閉包賦值給了 ashtml 屬性,這個閉包返回乙個代表 html 標籤的字元串。如果 text 值存在,該標籤就包含可選

值 text ;如果 text 不存在,該標籤就不包含文字。對於段落元素,根據 text 是 "some text" 還是 nil ,閉包會返回 "some

text

" 或者 "" 。

可以像實例方法那樣去命名、使用 ashtml 屬性。然⽽,由於 ashtml 是閉包而不是實例方法,如果你想改變特定 html 元素

的處理⽅式的話,可以用⾃定義的閉包來取代預設值。(實現重寫了)

例如,可以將乙個閉包賦值給 ashtml 屬性,這個閉包能在 text 屬性是 nil 時使用預設文字,這是為了避免返回乙個空的 html

標籤:let heading = htmlelement(name: "h1")

let defaulttext = "some default text"

heading.ashtml = else

上⾯的 htmlelement 實現和之前的實現一致,除了在 ashtml 閉包中多了乙個捕獲列表。這里,捕獲列表是 [unowned self] ,

表示「將 self 捕獲為無主引⽤而不是強引用」。

和之前一樣,我們可以建立並列印 htmlelement 實例:

var paragraph: htmlelement? = htmlelement(name: "p", text: "hello, world")

print(paragraph!.ashtml())

// 列印「hello, world

」使用捕獲列表後引用關係如下圖所示:

這一次,閉包以無主引用的形式捕獲 self ,並不會持有 htmlelement 實例的強引用。如果將 paragraph 賦值為nil , 

htmlelement 實例將會被銷毀,並能看到它的析構器列印出的訊息:

paragraph = nil

// 列印「p is being deinitialized」

你可以檢視《捕獲列表》章節,獲取更多關於捕獲列表的資訊。

個人筆記 跳板機(三十七)

scp 遠端拷貝,全量拷貝 每次都全量 rsync遠端傳輸模式一樣 push 推 scp rp etc root 172.16.1.31 opt pull 拉 scp root 172.16.1.31 opt xx tmp man幫助裡面單位是kbit s,拷貝的時候顯示的是mb s 也就是mbyt...

shell學習三十七天 引用

引用 案例,如果我想輸出乙個星號 使用echo 如何做?echo 這是肯定不行的,需要將 轉移,即 echo 這樣就引出了引用的概念.所為引用 是用來防止 shell 將某些你想要的東西解釋成不同的意義 如果你希望某些可能被 shell 視為個別引數的東西保持為單個引數 這時你就必須將其引用.引用的...

swift文件筆記 十七 協議

協議就是協議裡的屬性方法,在遵循協議的類 結構體 列舉中,必須要有實現。1.協議語法 protocol someprotocol 讀寫 var doesnotneedtobesettable int 唯讀,但實際實現中可以是讀寫 2.構造器要求 你可以在遵循協議的類中實現構造器,無論是作為指定構造器...