可能大家都知道如果在block中顯式或隱式地引用了self(比如引用了self的成員變量等),則會引發(fā)內(nèi)存泄漏志珍,但又會有人說,如果是類似于NSArray或者Animation的系統(tǒng)block中引用了self不會有問題控漠,這些經(jīng)驗應(yīng)當都會有一些事實的佐證,但這里面真正的機制是怎樣呢客蹋?
先了解下cocoa的block本身,在block的誕生之初怔球,由于編譯器還沒有很智能,所以程序員在使用的時候有些情況下還需要關(guān)注block從棧上復制到堆上的時機浮还,即手動調(diào)用Block_copy(比如并沒有引用作用域中的自動變量等情況)竟坛。
按照Working with Blocks給出的例子,在使用block時引起強引用循環(huán)時會導致嚴重的內(nèi)存泄漏钧舌,而大家要注意的是担汤,循環(huán)強引用的條件是block中引用了強引用的self,而另一必要條件是self也同時引用了block洼冻。
而實際的經(jīng)驗也會告訴你一件事情崭歧,那就是,只要定義的block不被其他對象持有撞牢,并且此block在添加到各線程中之后已經(jīng)執(zhí)行完畢率碾,則其中就算是因為self強引用了創(chuàng)建它的對象,也不會導致嚴格意義上的內(nèi)存泄漏屋彪,因為在執(zhí)行完畢之后所宰,block被真正的釋放(前提條件是沒有對此block的顯式引用且此block在添加到的各線程中也已經(jīng)執(zhí)行完畢了),則其對self的強引用也已經(jīng)被釋放了畜挥,只要此時self不要自己作去強引用這個block仔粥,就不會形成循環(huán)強引用,也不會形成永久的內(nèi)存泄漏蟹但。因為在block執(zhí)行完之后躯泰,其實self只要沒有其他對象的強引用,是已經(jīng)可以釋放了的华糖,雖然可能比原本釋放的時間推后了麦向。
所以其實大家真正怕的其實并不是在block中引用了self,因為這并不會導致循環(huán)強引用客叉,而是在block中強引用self所可能導致的這個block未被釋放所引起的self未被釋放磕蛇,因為在block傳遞過程中的任何一個環(huán)節(jié)都可以導致block被強引用,所以注意規(guī)避block中的self的強引用寫法確實可以很大程度上避免內(nèi)存泄漏十办,但這種寫法本身并不一定會帶來真正的內(nèi)存泄漏秀撇。
注:按照Using Blocks的說法,block字面量是代表block的基于棧本地數(shù)據(jù)結(jié)構(gòu)的地址向族。