注意以create,copy
作為關鍵字的函式都是需要釋放記憶體的,注意配對使用。比如:cgcolorcreate<-->cgcolorrelease
這部分不做詳細介紹,也是注意配對使用,需要說明的是,如果**中有部分檔案是mrc的,在已有檔案中加**的時候注意一下,不能都按照arc的方式處理。
arc已經為我們做了很多封裝,我們不必再顯示的呼叫retain,release,但是還是要注意迴圈引用的場景。
在此,常規的物件間的互相引用和block的迴圈引用大家都比較了解,這裡就不贅述了,羅列幾個我們**中的錯誤。
1. nstimer
nstimer會造成迴圈引用,timer會強引用target即self,一般self又會持有timer作為屬性,這樣就造成了迴圈引用。
那麼,如果timer只作為區域性變數,不把timer作為屬性呢?同樣釋放不了,因為在加入runloop的操作中,timer被強引用。而timer作為區域性變數,是無法執行invalidate的,所以在timer被invalidate之前,self也就不會被釋放。
所以我們要注意,不僅僅是把timer當作例項變數的時候會造成迴圈引用,只要申請了timer,加入了runloop,並且target是self,雖然不是迴圈引用,但是self卻沒有釋放的時機。如下方式申請的定時器,self已經無法釋放了。
nstimer *timer = [nstimer timerwithtimeinterval:5 target:self selector:@selector(commentanimation) userinfo:nil repeats:yes];
[[nsrunloop currentrunloop] addtimer:timer formode:nsrunloopcommonmodes];
每次任務結束時使用dispatch_after方法做延時操作。注意使用weakself,否則也會強引用self。
- (void)startanimation
);}
ws(weakself);
timer = dispatch_source_create(dispatch_source_type_timer, 0, 0, dispatch_get_main_queue());
dispatch_source_set_timer(timer, dispatch_time_now, 5 * nsec_per_sec, 1 * nsec_per_sec);
dispatch_source_set_event_handler(timer, ^);
dispatch_resume(timer);
2. nsnotification
使用block的方式增加notification,引用了self,在刪除notification之前,self不會被釋放,與timer的場景類似,其實這段**已經宣告了weakself,但是呼叫_eventmanger方法還是引起了迴圈引用。
也就是說,即使我們沒有呼叫self方法,_***
也會造成迴圈引用。
[[nsnotificationcenter defaultcenter] addobserverforname:kusersubscribenotification object:nil queue:nil usingblock:^(nsnotification *note)
}}
3. __block
__block
在mrc
中是不會增加引用的,可是在arc
中會增加,所以在arc中,只能使用__weak去打破迴圈引用。
__block myviewcontroller *weaksef = self;
_myviewcontroller.editblock = ^();
另外宣告一點,並非所有的block都需要使用weak來打破迴圈引用,如果self沒有持有block就不會造成迴圈引用(例如, 動畫block塊)。而有些地方之所以使用了__weak,是為了在[self dealloc]之後就不再執行了。在這種場景下使用weakself時,也需要注意,如果self被釋放了會不會引起異常。比如下面這段**把weakself取到的值作為入參,如果self釋放了,傳nil,引起crash:
[[httpcore sharedinstance] getrequestwithpath:url target:self params:params success:^(nsdictionary *result, nsurlrequest *request, nshttpurlresponse *response) failure:^(nserror *error) ];
4.performselector記憶體洩露
performselector延時呼叫的問題,
performselector關於記憶體管理的執行原理是這樣的:執行 [self performselector:@selector(method1:) withobject:self afterdelay:3]; 的時候,系統會將self的引用計數加1,執行完這個方法時,還會將self的引用計數減1,當方法還沒有執行的時候,要返回父檢視釋放當前檢視的時候,self的計數沒有減少到0,而導致無法呼叫dealloc方法,出現了記憶體洩露。
所以最後我的解決辦法就是取消那些還沒有來得及執行的延時函式,**很簡單:
[nsobject cancelpreviousperformrequestswithtarget:self]
當然你也可以乙個乙個得這樣用:
[nsobject cancelpreviousperformrequestswithtarget:self selector:@selector(method1:) object:nil]
加上了這個以後,dealloc方法就會被呼叫,問題解決!
為了安全還是
1.呼叫performa之前先單個取消一下
2.彈出viewcontroller單個取消一下
3. 還有 一些特殊情況業務操作需要過幾秒,是不要取消,比如要儲存一些資料。
iOS 記憶體洩漏的常見場景
注意以creat,copy作為關鍵字的函式都是需要釋放記憶體的,注意配對使用。比如 cgcolorcreate cgcolorrelease 這部分不做詳細介紹,也是注意配對使用,需要說明的是,如果 中有部分檔案是mrc的,在已有檔案中加 的時候注意一下,不能都按照arc的方式處理。arc已經為我們...
Golang 記憶體洩漏場景
雖然golang 的runtime 會 記憶體,但是本文列舉的場景仍然會造成記憶體洩漏。todo 此處需要了解下golang 的底層 memory block 分配知識 var s0 string 包級別變數 a demo purpose function.func f s1 string func...
常見的記憶體洩漏
vector v new vector 10 for int i 1 i 100 i 如果我們僅僅釋放引用本身,那麼 vector 仍然引用該物件,所以這個物件對 gc 來說是不可 的。因此,如果物件加入到vector 後,還必須從 vector 中刪除,最簡單的方法就是將 vector 物件設定為...