我之前寫了一段代碼
//Todo. maybe retain cycle.
self.movieWriter.newFrameCallback = ^{
[self.delegate appendFrame:self error:nil curduration:self.movieWriter.duration];
};
這段代碼會提示retain cycle萝玷。
先說這個retain cycle
Retain cycle符匾,翻譯成中文大概叫保留環(huán)吧往湿。既然父對象持有子對象研侣,而子對象會隨父對象釋放而釋放扫夜,那么楞泼,如果兩個對象相互為父對象怎么辦驰徊?
比如A和B兩個對象,A持有B堕阔,B同時也持有A棍厂,按照上面的規(guī)則,A只有B釋放之后才有可能釋放超陆,同樣B只有A釋放后才可能釋放牺弹,當雙方都在等待對方釋放的時候, retain cycle就形成了时呀,結(jié)果是例驹,兩個對象都永遠不會被釋放,最終內(nèi)存泄露退唠。
查考內(nèi)存管理原則
1鹃锈、默認strong,可選weak瞧预。strong下不管成員變量還是property屎债,每次使用指針指向一個對象,等于自動調(diào)用retain(), 并對舊對象調(diào)用release(),所以設(shè)為nil等于release垢油。
2盆驹、只要某個對象被任一strong指針指向,那么它將不會被銷毀滩愁,否則立即釋放躯喇,不用等runloop結(jié)束。所有strong指針變量不需要在dealloc中手動設(shè)為nil硝枉,iOS會自動處理廉丽,debug可以看到全部被置為nil,最先聲明的變量最后調(diào)用dealloc釋放妻味。
3正压、官方建議IBOutlet加上__weak,實際上不用加也會自動釋放责球;
4焦履、優(yōu)先使用私有成員變量,除非需要公開屬性才用property雏逾。
5嘉裤、避免循環(huán)引用,否則手動設(shè)置nil釋放栖博。
6屑宠、block方法常用聲明:@property (copy) void(^MyBlock)(void); 如果超出當前作用域之后仍然繼續(xù)使用block,那么最好使用copy關(guān)鍵字笛匙,拷貝到堆區(qū)侨把,防止棧區(qū)變量銷毀犀变。
7、創(chuàng)建block匿名函數(shù)之前一般需要對self進行weak化秋柄,否則造成循環(huán)引用無法釋放controller:
__weak MyController *weakSelf = self 或者 __weak __typeof(self) weakSelf = self;
執(zhí)行block方法體的時候也可以轉(zhuǎn)換為強引用之后再使用:
MyController* strongSelf = weakSelf;
if (!strongSelf) { return; }
所以获枝,應(yīng)該是要這么寫才不會有waring, 不會出現(xiàn)內(nèi)存泄漏骇笔。
__weak typeof(self) weakSelf = self;
self.movieWriter.newFrameCallback = ^{
[weakSelf.delegate appendFrame:weakSelf error:nil curduration:weakSelf.movieWriter.duration];
};