若是在網上搜關於內存管理最多的總結就是誰持有誰釋放。可是內存管理往多的說是有好多東西的,我今天只寫一下關於strong、weak和autoreleas(之後會寫片博客,會介紹到它們的底層運做)。在此也給想更深刻了解的夥伴們推薦本書一個日本前輩寫的Objective-C高級編程,我本身講內存管理梳理的差很少清晰的時,多虧了它。編程
關於內存管理,我原來有一段時間都對strong、weak傻傻的區分不清楚,也沒有多少興趣去了解。直到一天我真的在使用代理中碰到了神奇的內存泄漏,害死我了,通過調查鎖定了兇手就是weak,根本的罪魁禍首是我對修飾符使用的只知其一;不知其二。但願這點理解能起到一點點幫助。oop
a、區分strong、weak佈局
strong:strong爲強引用,是id類型對象和對象默認的全部權修飾符(咱們平時在@property中指定了屬性的修飾strong、weak、或者是assign,可是在建立其餘對象的時候,系統幫咱們默認加了_strong修飾符進行內存管理),使用strong修飾的對象在超出其變量做用域時,即該變量被廢棄時,會釋放其被賦予的對象。使用strong會對對象被持有對象的引用計數產生影響,當其持用一其餘對象的時候,會將其餘對象的引用計數加1,當出做用域強引用失效時,會釋放掉對其持有對象的持有。學習
weak:weak爲若引用。weak修飾的對象,當其持有其餘對象的時候不會對其餘對象的引用計數形成影響,weak的存在很好的解決掉了循環引用。當它所持有的對象銷燬時,weak修飾的對象會自動置nil。關於weak的實現我簡單的多說一點,由於我本身原來對此很好奇而後多方瞭解了下,在此分享給你們,若是有錯歡迎更但願你們糾正。代理
runtime會對註冊的類進行佈局,對於weak對象會放入一個hash表中。使用weak對象的內存地址做爲key,當weak對象指向的對象的引用計數爲0的時候執行置nil。執行過程爲以weak對象的內存地址爲索引,在hash表中找到對應的weak修飾對象,將其置爲nil。對象
b、做用的區分索引
討論他兩避免不了循環引用和自引用。說白了就是光使用strong容易出現內存泄漏即在對象出了做用域(也就是大括號)後不能獲得釋放。以下例子:內存
分別建立對象a、b,他們分別被對象A、B持有(當咱們沒有指定修飾權時,咱們建立的對象默認的修飾權爲_strong,也就是強引用)。而後對象B中有個成員變量objB又持有了a一次,對象A中的成員變量abjA有持有了b一次。這樣,就會造成循環引用。由於在出了做用域後A、B的強引用失效,釋放掉了對a、b的持有,可是他們中的成員變量並無釋放掉對於a、b的持有。此時發生內存泄漏,也就是咱們所說的循環引用。作用域
上面剛剛說過,weak不會對引用計數形成影響,也就不會影響到有關對象的釋放。因此咱們在關鍵部位使用weak修飾並不會形成對有關對象的引用計數形成影響,從而使得已經出了做用域可是有關該釋放的對象並不能獲得釋放,形成內存泄漏。博客
c、autoreleas有關問題
之因此說autoreleas是由於原先在網上學習內存管理這塊的時候被誤導過,在此但願你們注意。autoreleas釋放池中對對象的釋放我原來好奇過,上網查的時候最後造成的答案是做用域。可是隨着對O-C更加深刻的學習,發現了它對於其內部寄存對象的釋放是和runloop有關係的。
iOS程序由許多的runloop組成,每個runloop都會有一個Autorelease Pool並在末尾進行釋放。
好比咱們點擊一個button,一個button從等待到點擊到響應就存在一次循環,期間就前程到對象的建立和最後Autorelease Pool在runloop即將結束時的銷燬所有對象。