簡體   English   中英

為什么不在函數外部進行引用會創建保留周期?

[英]Why doesn't referencing outside of a function create retain cycle?

抱歉,但是我知道這是一個非常愚蠢的問題,我已經有點“知道”答案了,但是我需要有人清楚地向我解釋為什么答案是它的意思。

最近,在經歷了各種內存問題的噩夢調試之后,我對代碼的保留周期和內存泄漏有些迷戀/偏執,所以將來我希望將它們扼殺在萌芽狀態。 但是,在閱讀和學習了很多有關ARC的知識並保留了Swift的周期之后,盡管這很有意義,但我仍然沒有足夠的“直覺”或自然的感覺,以至於我有信心找到一個或一個我正在編碼中缺少一個。 因此,我開始變得有點偏執,因為我甚至沒有意識到就創建了包含基本內容的保留周期。

因此,考慮到這一點,為什么任何使用在其外部聲明的變量的普通函數都不會創建保留周期? 例如:

    class someClass {
        let a = "I'm letter a"
        let moreLetters = addLetters()
        func addLetters () -> String { 
            let newString = a + "bcdefg"
            return newString
        }
    }

在這種情況下,self.moreLetters引用函數addLetters,然后常量self.a是函數addLetters中的引用。 如果我不捕捉弱者/無主者,那么這會形成一個保留周期嗎? 在我看來,這種簡單的事情會引起問題是荒謬的……還是嗎? 像這樣的嵌套函數呢?

    func someFunction () -> String {
        let a = "I'm letter a"
        func addLetters () -> String { 
            let newString = a + "bcdefg"
            return newString
        }
        let moreLetters = addLetters()
        return moreLetters
    }

這還會造成保留周期嗎? (是的,我知道這是執行簡單任務的復雜方法;我只是以這段代碼為例來說明我的觀點)。

我是否變得超級偏執狂,並且對事情認真思考?

首先,您需要了解如何形成基本的保留周期。 當對象A同時強烈引用對象B時,會形成一個保留周期。 對象B也強烈指對象A。

讓我們看看您的第一段代碼。

class someClass {
    let a = "I'm letter a"
    let moreLetters = addLetters()
    func addLetters () -> String { 
        let newString = a + "bcdefg"
        return newString
    }
}

實際上,類本身永遠不會創建保留周期,因此讓我們添加一些代碼來創建對象:

var obj = someClass()

首先,將a初始化為“我是字母a”。 在此之后, moreLetters通過調用該方法初始化addLetters 方法返回后, moreLetters初始化為“ I'm letter abcdefg”。 到現在為止還挺好。

現在我們將obj設置為nil

obj = nil

如果形成了保留循環,則不會取消初始化obj 但是,實際上, obj被取消了初始化,因為沒有什么東西可以強烈引用obj

“等一下!” 您會說:“但是方法addLetters仍然引用someClass因為其中包含a !” 好吧,事實上, addLetters已經回來了! 因此,其中的所有內容都不再重要! 另外, addLetters屬於obj ,您已經將其設置為nil

現在,讓我們看一下您的第二個代碼:

func someFunction () -> String {
    let a = "I'm letter a"
    func addLetters () -> String { 
        let newString = a + "bcdefg"
        return newString
    }
    let moreLetters = addLetters()
    return moreLetters
}

保留循環不會形成,因為甚至沒有引用類型! 沒有要創建的對象。 您在第二個代碼中所做的全部工作就是使用字符串(它們是值類型)。 即使有一個類,也不會形成保留周期,因為正如我所說,當將obj設置為nil ,其中的所有方法都會“消失”,因為方法屬於對象。


那些必須寫[weak self]或保留周期表格的閉包呢?

這些閉包正在逃避閉包 普通閉包在返回后會被取消初始化。 但是,轉義的閉包由某些對象保留,因此它們不會立即取消初始化。 有關更多信息,請參見在Swift中轉義閉包

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM