在使用 Swift 語言進行開發的時候,很多朋友會莫名奇妙地遇到內存爆滿的問題,明明有 弧 ,明明釋放了內存,卻還是讓程序的內存佔用隨著循環而一路飆升。
這裡其實並不是出現了內存洩露,這其實是 弧 的一個機制:在每一個主 Runloop 結束的時候進行清理。也就是說,它有一套必要的緩存機制——畢竟,實時釋放的話誰能保證你的局部變量要不要留下來給後續的代碼使用呢?
但顯然,這個必要的機制在這個時候成了我們的噩夢,比如說:
1 2 3 4 5 |
func test() { for _ in 0..<999 { let a = loadBigData() } } |
這裡我們假定這個 loadBigData() 是一個加載文件略大又費事的動作,那麼按照想法,這個文件在每次循環都會被釋放——畢竟是個循環內的局部變量,但實際上由於 ARC 的緩存機制,內存就會一直變大。
這個時候,我們可以說 ARC 並不是很智能,所以一旦遇到這種情況,那麼就需要人工對 ARC 進行干預,來達到更好的內存管理效果。
在 Swift 中,我們使用這個全局函數 上市 FUNC autoreleasepool<結果>(調用 身體: () 投 -> 結果) 重新拋出 -> 結果
可以看到,它是一個泛型聲明,返回的類型根據你傳入的閉包而定。我們要做的就是將需要計算的內容放入這個函數中進行計算,這樣就相當於是臨時把為這個內容開放的內存標記為不要緩存,那麼 ARC 不會等到 Runloop 結束才回收,而是在用完後立即回收內存資源,比如說改成這樣:
1 2 3 4 5 6 7 |
func test() { for _ in 0..<999 { autoreleasepool { let a = loadBigData() } } } |
這樣,計算完成的內容就會立即被清理掉,程序的行為才真正符合我們的本意。
最後還是要補一句,這裡我們的 loadBigData() 指代的是一個加載大文件然後獲取想要的數據再返回的過程,並非初始化一個類,如果是通過類初始化比如 大法(網址:url) 這樣的初始化方法,ARC 是能夠自動管理的。這裡我們討論的是一種非常特殊的情況——畢竟大家編程這麼久,也並不一定會碰到幾次。
本文由 落格博客 原創撰寫:落格博客 » swift 中內存狂飆的問題
轉載請保留出處和原文鏈接:https://www.logcg.com/archives/2233.html