SlideShare a Scribd company logo
1 of 54
Download to read offline
消滅永⽣生不死吸⾎血⿁鬼物件的
ARC
1
Swift Girls
彼得潘
彼得潘簡介
App程式設計入⾨門:iPhone.iPad
Swift程式設計入⾨門
正職: 作家
副業: 專欄欄作家,⼯工程師,講師,顧問,家教,App評審,
App接案,企業包班,創業家,iOS APP ⾦金金牌擺渡⼈人
iOS App⼯工程師/外包廠商的⾯面試鑑賞師,
相關教學資源
• FB粉絲團: 愛瘋⼀一切為蘋果的彼得潘

http://www.facebook.com/iphone.peterpan
• 個⼈人網站

http://apppeterpan.strikingly.com
• medium: 彼得潘的App Neverland

https://medium.com/@apppeterpan
• GitBook: 彼得潘的iOS App開發便便利利貼

https://www.gitbook.com/book/apppeterpan/iosappcodestickies/
• FB社團: 彼得潘的蘋果App開發教室

https://www.facebook.com/groups/peterpanappclass/
相關教學資源
• 電⼦子報

http://strikingly.us12.list-manage.com/subscribe?u=afa877b4a57124636b33826b0&id=4dd6b92dbb
• SlideShare

http://www.slideshare.net/deeplovepan
• email: apppeterpan@gmail.com
• FB: https://www.facebook.com/deeplove.pan
• LINE: deeplovepeterpan
iOS的記憶體
• ⼩小⼩小的iPhone -> 少少的記憶體
• iPhone 7 plus: 3GB

iMac: 32GB
• App執⾏行行時只能得到⼀一部分的記憶體,不
能獨佔所有的記憶體
5
物件和記憶體
• App執⾏行行時,產⽣生的⼀一個個物件,佔據著記憶體。
• 儲存屬性設定的資料
• 儲存⽅方法的程式碼
class Baby {
var age = 1
var name = "peter"
func eat() {
}
func sleep() {
}
}
6
指到物件的屬性
class Baby {
var age = 0
var myRabbit = Rabbit()
}
class Rabbit {
var age = 0
}
7
每個物件佔據不同⼤大⼩小的記憶體
class Baby {
var age = 0
var weight = 10
var height = 100
}
class Rabbit {
var age = 0
}
8
⼈人⼝口爆炸
正常⼈人只能活100歲
9
• 只會建立物件
• 不會殺死物件
• 超過系統允許使⽤用的記憶體上限
• App被強制終結⽣生命 -> crash
物件爆炸
10
memory leak
記憶體爆炸
永⽣生不死的物件
11
ex:漏⽔水
噬⾎血童話(美)
https://www.youtube.com/watch?v=0fLf64z0OKY
⾎血⾊色入侵(瑞典)
https://www.youtube.com/watch?v=FNsJH_TMN_Q
12
記憶體爆炸實例例
ViewController.swift
@IBAction func createBaby(sender: Any) {
for i in 0…1000000 {
let cuteBaby = Baby()
babyArray.append(cuteBaby)
}
}
13
記憶體爆炸實例例
實機測試,
模擬器記憶體充⾜足,
不易易測出
App Crash
2015-11-10 13:58:52.515 ArcDemo[751:222661] Received memory warning.
2015-11-10 13:58:52.516 ArcDemo[751:222661] Received memory warning.
Message from debugger: Terminated due to memory issue
14
偵測記憶體⽤用量量
15
偵測記憶體⽤用量量
• instrument的Activity Monitor
16
記憶體爆掉前的警告
UIViewController
func didReceiveMemoryWarning()
減少記憶體⽤用量量,比⽅方移除⽤用不到的view
17
UIApplicationDelegate
func applicationDidReceiveMemoryWarning(_ application:
UIApplication)
ARC
• Automatic Reference Counting
• ⾃自動追蹤reference物件的數字。當數字為0
時,物件即死亡
• 只作⽤用在物件,不會作⽤用在 struct & enum
(struct & enum 是 value type,是複製的概
念念)
18
https://www.raywenderlich.com/134411/arc-memory-management-swift
以是否還有⼈人關⼼心物件,
決定物件的⽣生死
cuteDog
handsomeDog
cuteDog 什什麼是reference ?
19
class Dog {
var name:String
init(name:String) {
self.name = name
}
}
var cuteDog:Dog? = Dog(name: "⼩小⽩白")
var handsomeDog = cuteDog
cuteDog = nil
handsomeDog = nil
變數儲存物件的記憶體位置
邁向死亡的最後⼀一哩路路deinit
Dog.swift
class Dog {
func eat() {
}
deinit {
print("主⼈人,我即將死去,謝謝你愛過我")
}
}
請在project測試,在 playground 不容易易測試
20
物件死亡
override func viewDidLoad() {
super.viewDidLoad()
var cuteDog:Dog? = Dog()
cuteDog?.eat()
print("史努比,我會養你⼀一輩⼦子的。")
cuteDog = nil
print("sorry,你我緣份已盡。")
}
ViewController.swift
21
兩兩個只能活⼀一個
override func viewDidLoad() {
super.viewDidLoad()
var cuteDog:Dog = Dog()
cuteDog.eat()
print("史努比,我會養你⼀一輩⼦子的。")
cuteDog = Dog()
print("sorry,我愛上了了另⼀一隻狗,你我緣份已盡。")
}
史努比,我會養你⼀一輩⼦子的。
主⼈人,我即將死去,謝謝你愛過我
sorry,我愛上了了另⼀一隻狗,你我緣份已盡。
主⼈人,我即將死去,謝謝你愛過我
22
function裡宣告的變數(常數)

或function的參參數
test method執⾏行行完
後,變數cuteDog就⽤用不
到了了,因此也就沒有變
數指到⼩小狗物件。
ViewController.swift
func test() {
let cuteDog:Dog? = Dog()
cuteDog?.eat()
print("史努比,我會養你⼀一輩⼦子的。")
}
override func viewDidLoad() {
super.viewDidLoad()
self.test()
print("after test")
}
史努比,我會養你⼀一輩⼦子的。
主⼈人,我即將死去
after test
23
local 變數(常數)
類別的屬性
屬性將和類別建立的物件共存亡
override func viewDidLoad() {
super.viewDidLoad()
var cuteBaby:Baby = Baby()
}
ViewController.swift
class Baby {
var cuteDog = Dog()
deinit {
print("即將死去的寶寶")
}
}
Baby.swift
即將死去的寶寶
主⼈人,我即將死去
24
屬性將和類別建立的物件共存亡
25
cuteDog
cuteBaby
class Baby {
var name:String = "peter"
var cuteDog:Dog?
deinit {
print("baby (self.name) dead")
}
}
class Dog {
var name:String = ""
deinit {
print("dog (self.name) dead")
}
}
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
var cuteBaby1:Baby? = Baby()
cuteBaby1?.name = "andy"
cuteBaby1?.cuteDog = Dog()
cuteBaby1?.cuteDog?.name = "tony"
var cuteBaby2:Baby? = Baby()
cuteBaby2?.name = "jeff"
cuteBaby2?.cuteDog = cuteBaby1?.cuteDog
cuteBaby1 = nil
}
26
例例⼦子
全域變數(常數)
var cuteBaby:Baby = Baby()
class ViewController: UIViewController {
唯有設為nil或改變它指向的⽬目標,
才能切斷他和物件的關聯聯
27
當物件被加到array或dictionary時,
也會增加reference
當物件存在array裡,
表⽰示物件
正被需要,關⼼心著
class ViewController: UIViewController,
UITextFieldDelegate {
var babyArray = [Baby]()
override func viewDidLoad() {
super.viewDidLoad()
let baby = Baby()
self.babyArray.append(baby)
}
28
當物件從array或dictionary移除時,
或是array或dictionary死亡時,
物件的reference將減少
class ViewController: UIViewController,
UITextFieldDelegate {
var babyArray = [Baby]()
override func viewDidLoad() {
super.viewDidLoad()
let baby = Baby()
self.babyArray.append(baby)
self.babyArray = []
}
29
reference cycle
class Baby {
var pet:Dog?
deinit {
print("⼈人⽣生⾃自古誰無死,留留取丹丹⼼心照汗青")
}
}
Baby.swift
Dog.swift
class Dog {
var owner:Baby?
deinit {
print("主⼈人,我即將死去,謝謝你愛過我")
}
} 30
reference cycle
override func viewDidLoad() {
super.viewDidLoad()
var cuteBaby:Baby? = Baby()
var cuteDog:Dog? = Dog()
cuteDog?.owner = cuteBaby
cuteBaby?.pet = cuteDog
}
ViewController.swift
不死的⼈人和狗
31
reference cycle
32
pet
cuteBaby cuteDog
owner
Xcode 8 的
Memory Graph Debugger
33
https://developer.apple.com/library/content/documentation/DeveloperTools/Conceptual/debugging_with_xcode/chapters/special_debugging_workflows.html
Xcode 8 的
Memory Graph Debugger
34
記錄物件如何⽣生成 ?
35
找到不死的吸⾎血⿁鬼寶寶
36
利利⽤用weak解決cycle
Baby.swift
class Baby {
weak var pet:Dog?
deinit {
print("⼈人⽣生⾃自古誰無死,留留取丹丹⼼心照汗青")
}
}
1. 不關⼼心物件,不會增加reference
2. 當物件死亡時,變數會被設成nil
37
利利⽤用weak解決cycle
38
pet
cuteBaby cuteDog
owner
利利⽤用weak解決cycle
override func viewDidLoad() {
super.viewDidLoad()
var cuteBaby:Baby? = Baby()
var cuteDog:Dog? = Dog()
cuteDog?.owner = cuteBaby
cuteBaby?.pet = cuteDog
print("我親愛的(cuteBaby?.pet)")
cuteDog = nil
print("我親愛的(cuteBaby?.pet)")
}
我親愛的Optional(ArcDemo.Dog)
主⼈人,我即將死去,謝謝你愛過我
我親愛的nil
⼈人⽣生⾃自古誰無死,留留取丹丹⼼心照汗青
ViewController.swift
39
ex: 當埃及艷后死掉後,
忘記埃及艷后的名字,
才不會難過 程式才不會危險
weak只能宣告optional的變數
40
利利⽤用unowned解決cycle
指到的物件死亡時,不會被⾃自動設為nil。
如果存取死亡物件將讓App crash
適合宣告非optional的變數(常數)
41
unowned
class Baby {
unowned var pet:Dog
init(pet:Dog) {
self.pet = pet
}
deinit {
print("⼈人⽣生⾃自古誰無死,留留取丹丹⼼心照汗青")
}
}
Baby.swift
42
unowned
ViewController.swift
43
存取已經死掉的物件 -> 殭屍是很危險的
Address Sanitizer
讓程式停在有問題的程式碼
(存取有問題的記憶體)
44
closure的reference cycle
class Rabbit {
let name: String
var actionClosure: (() -> ())!
init(name: String) {
self.name = name
self.actionClosure = {
print("我是全天下最可愛的(self.name)")
}
}
func performAction() {
actionClosure()
}
deinit {
print("死了了都要愛")
}
}
Rabbit.swift
在closure裡存取外部物件,
因為之後可能會⽤用到物件,因此延長物件壽
命(增加它的reference)
45
closure的reference cycle
override func viewDidLoad() {
super.viewDidLoad()
var cuteRabbit:Rabbit? = Rabbit(name: "彼得兔")
}
ViewController.swift
cuteRabbit的actionClosure連結到兔⼦子物件,所以當cuteRabbit設為nil時,
仍然有reference,因此兔⼦子不會死
46
讓兔⼦子死掉的第⼀一種⽅方法
override func viewDidLoad() {
super.viewDidLoad()
var cuteRabbit:Rabbit? = Rabbit(name: "彼得兔")
cuteRabbit?.actionClosure = nil
}
八百萬種死法
常常忘記先將closure設為nil
closure不⾒見見得能設為nil,比⽅方它不是optional,
或者它是傳入function的參參數
47
capture list
init(name: String) {
self.name = name
self.actionClosure = { [unowned self] in
print("我是全天下最可愛的(self.name)")
}
}
Rabbit.swift
利利⽤用[ ]指定不關⼼心,不想增加reference的物件
利利⽤用unowned
[ ] 裡可有多個物件,以逗號分隔
48
capture list
init(name: String) {
self.name = name
self.actionClosure = { [weak self] in
if self != nil {
print("我是全天下最可愛的(self!.name)")
}
}
}
Rabbit.swift
weak將成為optional
49
當傳入function的參參數為closure時
若若此closure⽤用到某個物件,也會增加物件的reference
要等function執⾏行行完,物件的reference才會減少
當傳入function的參參數為closure時
override func viewDidLoad() {
super.viewDidLoad()
var cuteBaby:Baby = Baby()
cuteBaby.name = "Jeff"
let urlStr = "https://res.cloudinary.com/hrscywv4p/image/upload/
c_limit,f_auto,h_3000,q_80,w_1200/v1/271374/http_s3.amazonaws.com_feather-files-
aviary-prod-us-
east-1_f5da8ea5e_2015-03-12_723490bbf79e44a788f5cd2516fefd46_myvzle.jpg"
let url = URL(string: urlStr)
let urlRequest = URLRequest(url: url!, cachePolicy:.returnCacheDataElseLoad,
timeoutInterval: 30)
let task = URLSession.shared.dataTask(with: urlRequest) {
(data:Data?, response:URLResponse?, err:Error?) -> Void in
print("cuteBaby in closure (cuteBaby)”)
}
task.resume()
print("viewDidLoad finish")
}
cuteBaby的reference count增加
viewDidLoad finish
cuteBaby in closure Test.Baby
baby Jeff dead
當傳入function的參參數為closure時
override func viewDidLoad() {
super.viewDidLoad()
var cuteBaby:Baby = Baby()
cuteBaby.name = "Jeff"
let urlStr = "https://res.cloudinary.com/hrscywv4p/image/upload/
c_limit,f_auto,h_3000,q_80,w_1200/v1/271374/http_s3.amazonaws.com_feather-files-
aviary-prod-us-
east-1_f5da8ea5e_2015-03-12_723490bbf79e44a788f5cd2516fefd46_myvzle.jpg"
let url = URL(string: urlStr)
let urlRequest = URLRequest(url: url!, cachePolicy:.returnCacheDataElseLoad,
timeoutInterval: 30)
let task = URLSession.shared.dataTask(with: urlRequest) { [weak cuteBaby]
(data:Data?, response:URLResponse?, err:Error?) -> Void in
print("cuteBaby in closure (cuteBaby)”)
}
task.resume()
print("viewDidLoad finish")
}
cuteBaby的reference count不增加
viewDidLoad finish
baby Jeff dead
cuteBaby in closure nil
當傳入function的參參數為closure時
override func viewDidLoad() {
super.viewDidLoad()
let urlStr = "https://res.cloudinary.com/hrscywv4p/image/upload/
c_limit,f_auto,h_3000,q_80,w_1200/v1/271374/http_s3.amazonaws.com_feather-files-
aviary-prod-us-
east-1_f5da8ea5e_2015-03-12_723490bbf79e44a788f5cd2516fefd46_myvzle.jpg"
let url = URL(string: urlStr)
let urlRequest = URLRequest(url: url!, cachePolicy:.returnCacheDataElseLoad,
timeoutInterval: 30)
let task = URLSession.shared.dataTask(with: urlRequest) { [weak self]
(data:Data?, response:URLResponse?, err:Error?) -> Void in
if let data = data {
self?.imageView.image = UIImage(data: data)
}
}
task.resume()
print("viewDidLoad finish")
}
ex: controller download image
從 controller A 回到前⼀一⾴頁時, controller A 應該要⾺馬上死掉,
不該等圖片下載完才死掉
畫⾯面上的元件
當元件被加到view上時,表⽰示其正被需要,關⼼心著,不能死,所以會增加reference
當元件從view上移除,或是容納它的view死亡時,reference將減少
所以IBOutlet連結到程式時,預設是weak。
54

More Related Content

More from 彼得潘 Pan

第一次程式親密接觸
第一次程式親密接觸第一次程式親密接觸
第一次程式親密接觸彼得潘 Pan
 
打造你的第一個iPhone APP
打造你的第一個iPhone APP打造你的第一個iPhone APP
打造你的第一個iPhone APP彼得潘 Pan
 
你的程式開發初體驗 (以Swift為例)
你的程式開發初體驗 (以Swift為例)你的程式開發初體驗 (以Swift為例)
你的程式開發初體驗 (以Swift為例)彼得潘 Pan
 
Standford 2015 week9
Standford 2015 week9Standford 2015 week9
Standford 2015 week9彼得潘 Pan
 
Standford 2015 week8
Standford 2015 week8Standford 2015 week8
Standford 2015 week8彼得潘 Pan
 
Standford 2015 week7: 1. Unwind Segues, Alerts, Timers, View Animation 2. Dyn...
Standford 2015 week7: 1. Unwind Segues, Alerts, Timers, View Animation 2. Dyn...Standford 2015 week7: 1. Unwind Segues, Alerts, Timers, View Animation 2. Dyn...
Standford 2015 week7: 1. Unwind Segues, Alerts, Timers, View Animation 2. Dyn...彼得潘 Pan
 
Standford 2015 week6
Standford 2015 week6Standford 2015 week6
Standford 2015 week6彼得潘 Pan
 
Standford 2015 week5: 1.View Controller Lifecycle, Autolayout 2. Scroll View ...
Standford 2015 week5: 1.View Controller Lifecycle, Autolayout 2. Scroll View ...Standford 2015 week5: 1.View Controller Lifecycle, Autolayout 2. Scroll View ...
Standford 2015 week5: 1.View Controller Lifecycle, Autolayout 2. Scroll View ...彼得潘 Pan
 
Standford 2015 week4: 1.Protocols and Delegation, Gestures 2. Multiple MVCs
Standford 2015 week4: 1.Protocols and Delegation, Gestures 2. Multiple MVCsStandford 2015 week4: 1.Protocols and Delegation, Gestures 2. Multiple MVCs
Standford 2015 week4: 1.Protocols and Delegation, Gestures 2. Multiple MVCs彼得潘 Pan
 
Standford 2015 week3: Objective-C Compatibility, Property List, Views
Standford 2015 week3: Objective-C Compatibility, Property List, ViewsStandford 2015 week3: Objective-C Compatibility, Property List, Views
Standford 2015 week3: Objective-C Compatibility, Property List, Views彼得潘 Pan
 
Standford 2015 iOS讀書會 week2: 1. Applying MVC 2. More Swift and Foundation Fra...
Standford 2015 iOS讀書會 week2: 1. Applying MVC 2. More Swift and Foundation Fra...Standford 2015 iOS讀書會 week2: 1. Applying MVC 2. More Swift and Foundation Fra...
Standford 2015 iOS讀書會 week2: 1. Applying MVC 2. More Swift and Foundation Fra...彼得潘 Pan
 
Standford 2015 iOS讀書會 week1: 1.Logistics , iOS 8 Overview 2. More Xcode and S...
Standford 2015 iOS讀書會 week1: 1.Logistics , iOS 8 Overview 2. More Xcode and S...Standford 2015 iOS讀書會 week1: 1.Logistics , iOS 8 Overview 2. More Xcode and S...
Standford 2015 iOS讀書會 week1: 1.Logistics , iOS 8 Overview 2. More Xcode and S...彼得潘 Pan
 
打造你的第一個 iOS App
打造你的第一個 iOS App  打造你的第一個 iOS App
打造你的第一個 iOS App 彼得潘 Pan
 

More from 彼得潘 Pan (15)

第一次程式親密接觸
第一次程式親密接觸第一次程式親密接觸
第一次程式親密接觸
 
打造你的第一個iPhone APP
打造你的第一個iPhone APP打造你的第一個iPhone APP
打造你的第一個iPhone APP
 
你的程式開發初體驗 (以Swift為例)
你的程式開發初體驗 (以Swift為例)你的程式開發初體驗 (以Swift為例)
你的程式開發初體驗 (以Swift為例)
 
Standford 2015 week9
Standford 2015 week9Standford 2015 week9
Standford 2015 week9
 
Standford 2015 week8
Standford 2015 week8Standford 2015 week8
Standford 2015 week8
 
Standford 2015 week7: 1. Unwind Segues, Alerts, Timers, View Animation 2. Dyn...
Standford 2015 week7: 1. Unwind Segues, Alerts, Timers, View Animation 2. Dyn...Standford 2015 week7: 1. Unwind Segues, Alerts, Timers, View Animation 2. Dyn...
Standford 2015 week7: 1. Unwind Segues, Alerts, Timers, View Animation 2. Dyn...
 
Standford 2015 week6
Standford 2015 week6Standford 2015 week6
Standford 2015 week6
 
Standford 2015 week5: 1.View Controller Lifecycle, Autolayout 2. Scroll View ...
Standford 2015 week5: 1.View Controller Lifecycle, Autolayout 2. Scroll View ...Standford 2015 week5: 1.View Controller Lifecycle, Autolayout 2. Scroll View ...
Standford 2015 week5: 1.View Controller Lifecycle, Autolayout 2. Scroll View ...
 
Standford 2015 week4: 1.Protocols and Delegation, Gestures 2. Multiple MVCs
Standford 2015 week4: 1.Protocols and Delegation, Gestures 2. Multiple MVCsStandford 2015 week4: 1.Protocols and Delegation, Gestures 2. Multiple MVCs
Standford 2015 week4: 1.Protocols and Delegation, Gestures 2. Multiple MVCs
 
Standford 2015 week3: Objective-C Compatibility, Property List, Views
Standford 2015 week3: Objective-C Compatibility, Property List, ViewsStandford 2015 week3: Objective-C Compatibility, Property List, Views
Standford 2015 week3: Objective-C Compatibility, Property List, Views
 
Standford 2015 iOS讀書會 week2: 1. Applying MVC 2. More Swift and Foundation Fra...
Standford 2015 iOS讀書會 week2: 1. Applying MVC 2. More Swift and Foundation Fra...Standford 2015 iOS讀書會 week2: 1. Applying MVC 2. More Swift and Foundation Fra...
Standford 2015 iOS讀書會 week2: 1. Applying MVC 2. More Swift and Foundation Fra...
 
Standford 2015 iOS讀書會 week1: 1.Logistics , iOS 8 Overview 2. More Xcode and S...
Standford 2015 iOS讀書會 week1: 1.Logistics , iOS 8 Overview 2. More Xcode and S...Standford 2015 iOS讀書會 week1: 1.Logistics , iOS 8 Overview 2. More Xcode and S...
Standford 2015 iOS讀書會 week1: 1.Logistics , iOS 8 Overview 2. More Xcode and S...
 
打造你的第一個 iOS App
打造你的第一個 iOS App  打造你的第一個 iOS App
打造你的第一個 iOS App
 
為愛打造App
為愛打造App為愛打造App
為愛打造App
 
iOS 7 SDK特訓班
iOS 7 SDK特訓班iOS 7 SDK特訓班
iOS 7 SDK特訓班
 

消滅永生不死吸血鬼物件的 ARC