2016-08-25 62 views
1

我剛剛在ARC上提供了一個教程,並提供了此代碼。ARC以及它如何工作。

以下ViewController類及其下面的Vehicle類。

我從中得到的結果是,ARC基本上追查一個實例化的類併爲它分配一塊內存。由於創建實例的「強」引用,因此增加了實例有多少引用的增量。一旦所有這些設置爲零,ARC就會從內存中釋放該實例。教練還說了一些話,一旦所有的引用沒有被使用,它就從內存中釋放。我並不完全理解它們沒有被「使用」的部分,所以我決定添加一個按鈕,該按鈕顯示另一個視圖控制器,這些視圖控制器空白且沒有代碼。我想如果我導航到下一個視圖控制器,deinit將被視爲視圖控制器1中的引用,現在不會被使用,因此會從內存中釋放。事實並非如此,並且deinit並沒有被調用。因此,我想知道,除非將它們設置爲零,否則引用會留在內存中嗎?

問題的第2部分:另外,當你回答這個問題時,我也有另一個問題,我也想知道ARC是否僅適用於類實例並引用它,因爲我看過的每一篇文檔或教程似乎只提到類實例。例如,如果我設置了var number = 2 var othernumber = number,「號碼」是否也存儲在內存中,並且只有在所有對它的引用都爲零之前才被釋放。如果情況也是如此,那麼同樣的問題適用,即將所有引用設置爲等於從內存釋放的唯一方式?對於冗長的問題抱歉,但對於內存概念我很新穎。

import UIKit 

class ViewController: UIViewController { 


var ref1: Vehicle? 
var reference2: Vehicle? 
var ref3: Vehicle? 
var timer: NSTimer! 
var count = 0 
override func viewDidLoad() { 
    super.viewDidLoad() 

    ref1 = Vehicle(kind: "Car") 
    reference2 = ref1 
    ref3 = ref1 

    timer = NSTimer.scheduledTimerWithTimeInterval(1.0, target: self, selector: #selector(tick), userInfo: nil, repeats: true) 


} 


func tick() { 
count++ 

    if count >= 3 { 
     ref3 = nil 
     reference2 = nil 



    } 

    if count == 5 { 
    ref1 = nil 


    } 


} 

}

class Vehicle { 

let type: String 


init(kind: String){ 
self.type = kind 
print("\(type) is being initialized") 
//when the class is instantiated, we get an initialization message. When class is deallocated, we get a deinit message. As in, all strong references are gone, we can deinitialize. 


} 
deinit { 
//class vehicle not in memory anymore as all strong references to it have been destroyed. This will be tested with segue as well. 
    print("\(type) is being deinitialized") 

}} 

回答

3
  1. 的 「用過的」 術語是混亂/誤導(或者在最好的,不精確)。使用ARC時,只有在沒有剩餘的強引用時,對象纔會被釋放,簡單明瞭。如果你所有這些強引用,或者那些強引用都超出了範圍,那就是當對象被釋放的時候。

    順便提一下,請注意scheduledTimerWithTimeInterval確立了自己對其目標的強烈參考。你必須invalidate定時器來解決這個強大的參考。

  2. ARC僅適用於參考類型(即class實例)。它根本不適用於值類型(如數字類型或struct類型)。

    因此,考慮

    var number = 2 
    var othernumber = number 
    

    othernumber不引用number。它製作一份副本。這是一個新值,它的值恰好與number的值相同。有關從參考類型區分Swift值類型的討論,請參閱WWDC 2015 Building Better Apps with Value Types。 (順便說一下,複雜值類型的幕後內存管理實際上比簡單的值類型更復雜,但它在這個對話中並不真正相關,但在視頻中會詳細討論感興趣。)

+0

感謝清除那個Rob,儘管在什麼情況下,一個強烈的引用會落在「超出範圍」 – slimboy

+0

同樣,我猜測值類型,它們也被分配到內存和釋放。程序員是否必須自己釋放它們才能保留內存空間? – slimboy

+0

謝謝你清理那個,我現在明白了。 – slimboy

1

這是一個很大的問題。

爲了理解ARC,您確實需要了解手動引用計數。

引用計數是一種跟蹤哪些對象仍在使用,哪些可以被釋放的方法。

在手動引用計數中,對象具有保留計數。

您向對象發送保留消息以增加保留計數,並釋放以減少保留計數。如果向對象發送釋放消息會導致其保留計數降至0,則會釋放/釋放該對象。

還有一個autorelease消息,它將該對象添加到「自動釋放池」中。每次您的代碼返回並訪問事件循環時,autorelease池中的所有對象都會在每次處於autorelease池時發送釋放消息。 (您可以向對象發送多個autorelease消息,但忽略該消息。)如果您沒有對它們執行任何特殊操作,Autorelease對於返回消失的臨時對象很有用。一個自動釋放的對象會在當前調用鏈期間停留,但是如果沒有人保留它,代碼返回時就會釋放它。

創建對象並將其返回給所有者,引用計數爲1,並且所有者負責在對象完成時向對象發送釋放消息。

在手動引用計數中,您必須在代碼中的正確位置放置保留,釋放和自動釋放調用,以表達您的內存管理意圖。弄錯它會導致內存泄漏或崩潰。

ARC使用所有上述機制,但編譯器分析您的代碼併爲您插入保留,釋放和autorelease調用。它還將多餘的保留/釋放呼叫剝離到最低要求。

在ARC中,您只需將變量聲明爲強或弱,然後編譯器完成剩下的工作。還有一些小問題,但大多數情況下,您不必擔心內存管理問題。

將對象存儲在強變量中會導致編譯器生成保留調用。清零強變量會導致編譯器向對象發送釋放消息。

與垃圾收集不同,系統不必停止並在內存上執行耗時的清理傳遞。只要沒有任何強引用,對象就會被釋放。

相關問題