★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
➤微信公衆號:山青詠芝(shanqingyongzhi)
➤博客園地址:山青詠芝(https://www.cnblogs.com/strengthen/)
➤GitHub地址:https://github.com/strengthen/LeetCode
➤原文地址:http://www.javashuo.com/article/p-swmrnhtm-mb.html
➤若是連接不是山青詠芝的博客園地址,則多是爬取做者的文章。
➤原文已修改更新!強烈建議點擊原文地址閱讀!支持做者!支持原創!
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★html
目錄:[Swift]通天遁地Swiftgit
本文將演示使用Instruments Allocations工具檢測應用程序中的內存泄漏問題。github
內存溢出 out of memory:是指程序在申請內存時,沒有足夠的內存空間供其使用,出現out of memory;好比申請了一個integer,但給它存了long才能存下的數,那就是內存溢出。swift
內存泄露 memory leak:是指程序在申請內存後,沒法釋放已申請的內存空間,一次內存泄露危害能夠忽略,但內存泄露堆積後果很嚴重,不管多少內存,早晚會被佔光。安全
在項目文件夾【DemoApp】上點擊鼠標右鍵,彈出右鍵菜單。微信
【New File】->【Swift File】->【Next】->【Save As】:People.swift->【Create】ide
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】 post
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對象,二者內存分配和回收的詳細流水記錄。