1. 程式人生 > >[Swift通天遁地]七、數據與安全-(11)如何檢測應用程序中的內存泄露

[Swift通天遁地]七、數據與安全-(11)如何檢測應用程序中的內存泄露

idt 無法 構建 inside selector () ive 如何 文字

本文將演示使用Instruments Allocations工具檢測應用程序中的內存泄漏問題。

內存溢出 out of memory:是指程序在申請內存時,沒有足夠的內存空間供其使用,出現out of memory;比如申請了一個integer,但給它存了long才能存下的數,那就是內存溢出。

內存泄露 memory leak是指程序在申請內存後,無法釋放已申請的內存空間,一次內存泄露危害可以忽略,但內存泄露堆積後果很嚴重,無論多少內存,遲早會被占光。

在項目文件夾【DemoApp】上點擊鼠標右鍵,彈出右鍵菜單。

【New File】->【Swift File】->【Next】->【Save As】:People.swift->【Create】

 1 import Foundation
 2 //主人類
 3 class People
 4 {
 5     //名稱屬性
 6     var name : String
 7     //主人的寵物
 8     var pet : Pet?
 9     
10     //添加一個初始化方法,並以名稱作為參數
11     init(name:String)
12     {
13         //設置對象的名稱屬性
14         self.name = name
15         //初始化日誌
16         print("People is initialized.
") 17 } 18 19 //添加一個析構方法 20 deinit 21 { 22 //析構日誌 23 print("People is deinitialized.") 24 } 25 }

使用相同的方式創建另一個類文件【Pet.swift】

 1 import Foundation
 2 //寵物類
 3 class Pet
 4 {
 5     //名稱屬性
 6     var name : String
 7     //寵物的主人屬性
 8     var master : People?
 9
10 //添加一個初始化方法,並以名稱作為參數 11 init(name:String) 12 { 13 //設置名稱屬性 14 self.name = name 15 //輸出初始化日誌 16 print("Pet is initialized.") 17 } 18 19 //添加一個析構方法 20 deinit 21 { 22 //析構日誌 23 print("Pet is deinitialized.") 24 } 25 }

在項目導航區,打開視圖控制器的代碼文件【ViewController.swift】

 1 import UIKit
 2 
 3 class ViewController: UIViewController {
 4 
 5     override func viewDidLoad() {
 6         super.viewDidLoad()
 7         // Do any additional setup after loading the view, typically from a nib.
 8         
 9         //添加一個按鈕,當用戶點擊該按鈕時,創建主人對象和寵物對象。
10         let button = UIButton(frame: CGRect(x: 0, y: 0, width: 280, height: 44))
11         //將按鈕控件放置在根視圖的中心位置
12         button.center = self.view.center
13         //設置正常狀態下的標題文字
14         button.setTitle("PeopleAndPet", for: .normal)
15         //設置按鈕的背景顏色為橙色
16         button.backgroundColor = UIColor.orange
17         //給按鈕綁定點擊事件
18         button.addTarget(self,
19                          action: #selector(ViewController.peopleAndPet), 
20                          for: UIControl.Event.touchUpInside)
21         
22         //設置根視圖的背景顏色
23         self.view.backgroundColor = UIColor.orange
24         //並把按鈕控件添加到根視圖
25         self.view.addSubview(button)
26     }
27     
28     //添加一個方法,用來響應按鈕的點擊事件
29     @objc func peopleAndPet()
30     {
31         //添加一個主人對象和一個寵物對象
32         var master:People?
33         var dog:Pet?
34         
35         //對兩個對象進行初始化操作,並設置它們的名稱屬性。
36         master = People(name: "Jerry")
37         dog = Pet(name: "Dog")
38         
39         //設置主人的寵物屬性
40         //設置寵物的主人屬性
41         //使兩個對象相互引用,
42         //由於兩個對象互相引用,所以兩個對象並不會在內存中被釋放。
43         master!.pet = dog        
44         dog!.master = master       
45 
46         //將兩個對象置空
47         master = nil
48         dog = nil
49     }
50 
51     override func didReceiveMemoryWarning() {
52         super.didReceiveMemoryWarning()
53         // Dispose of any resources that can be recreated.
54     }
55 }

啟動按鈕右下角箭頭選擇:【Build for Profiling】性能分析構建選項

此時將進入性能分析窗口,在【Instrument Detail】過濾輸入框內,輸入類名:People

由於尚未創建主人對象,所以在內存分配摘要列表中的搜索結果為空。

使用【Alt】+【Tab】切換至自動打開的模擬器窗口,

點擊模擬器中創建的應用程序按鈕。

由於兩個對象互相引用,所以兩個對象並不會在內存中被釋放。

此時在內存分配摘要列表中,顯示了一條主人對象的內存分配記錄。

選擇該條內存分配記錄。點擊右側的小箭頭,顯示內存分配的地址信息。

接著選擇內存地址,點擊右側的【擴展細節圖標】(感嘆號樣式)。

在列表中顯示的堆棧序列,其中黑色的代碼為開發者編寫的代碼。

鼠標雙擊黑色的代碼,在左側區域顯示該代碼。

點擊代碼界面右上角的開發軟件圖標,,打開Xcode.

現在來修改People類,將Pet對象的引用修改為弱引用,

以解決內存泄露的問題。

 1 import Foundation
 2 //主人類
 3 class People
 4 {
 5     //名稱屬性
 6     var name : String
 7     //主人的寵物
 8     //將寵物對象的引用修改為弱引用。
 9     //就不會產生內存泄露的問題。
10     weak var pet : Pet?
11     
12     //添加一個初始化方法,並以名稱作為參數
13     init(name:String)
14     {
15         //設置對象的名稱屬性
16         self.name = name
17         //初始化日誌
18         print("People is initialized.")
19     }
20     
21     //添加一個析構方法
22     deinit
23     {
24         //析構日誌
25         print("People is deinitialized.")
26     }
27 }

在【Instrument Detail】過濾輸入框內,輸入類名:People

在內存分配摘要列表中,顯示的搜索結果為空。

說明People對象和Pet對象,已經在內存中被正確的釋放。

在默認情況下,顯示的是已創建和被持有的內存分配,

勾選【Allocation Lifespan】區域的【All Allocations】所有的內存分配選項。

點擊右側的小箭頭,顯示內存分配的地址信息。

繼續點擊內存地址右側的小箭頭,查看內存分配的詳細信息。

在內存分配列表中,顯示了內存空間的創建時間,以及其他相關的信息。

選擇【Static】->【Allocations List】內存分配列表選項。

然後在搜索框內,繼續添加Pet類名。

點擊輸入框左側的下拉箭頭,彈出選項列表。

選擇【Matches Any】匹配任意選項,查找和People對象和Pet對象有關的內存分配記錄。

點擊【Detail】細節標簽,顯示選項的列表。選擇【Console】控制臺選項。查詢內存分配的日誌信息,

此時在控制臺輸出了People對象和Pet對象,兩者內存分配和回收的詳細流水記錄。

[Swift通天遁地]七、數據與安全-(11)如何檢測應用程序中的內存泄露