1.訪問了一個已經(jīng)被釋放的對象
遇到上圖情況的原因是這個數(shù)組的對象已經(jīng)被釋放,但是卻還有指針指向這個對象,這時訪問這個指針指向的內(nèi)存就會crash.還有一種情況就是這個數(shù)組在定義的時候使用的是成員變量_array,
解決辦法:
使用前判斷是否為空,釋放后要置空.將這個成員變量_array換成self.array或者在字面量的后面加上mutableCopy.
適當使用autorelease.有些時候不能知道自己創(chuàng)建的對象什么時候要進行釋放,可以使用autorelease,但是不鼓勵使用.因為autorelease的對象要等到最近的一個autoreleasepool銷毀的時候才會銷毀,如果自己知道什么時候會用完這個對象,當然立即釋放效率要更高.還有一種情況釋放池會被釋放就是runloop的狀態(tài)被切換的時候.
2.訪問數(shù)組類對象越界或插入了空對象.
'-[__NSArray0 isEqualToString:]: unrecognized selector sent to instance 0x7faaa3e001a0'
這個是插入了一個空的對象,解決方法使用數(shù)組時注意下標是否越界.插入對象前判斷該對象是否為空.
'*** -[__NSArrayM objectAtIndex:]: index 2 beyond bounds [0 .. 1]'
數(shù)組越界的問題經(jīng)常出現(xiàn),最簡單的現(xiàn)象就是下圖的樣子
3.訪問了不存的方法
objc的方法調(diào)用跟c++很不一樣.c++在編譯的時候就已經(jīng)綁定了類和方法,一個類不可能調(diào)用了一個不存在的方法,否則就報編譯錯誤.而objc則是在runtime的時候才取查找應(yīng)該調(diào)用哪一個方法.
調(diào)用一個不存在的方法,可以編譯通過,運行時直接掛掉,
reason: '-[WSMainViewController methodNotExist]:unrecognized selector sent to instance 0x1dd96160'</pre>
這種類型的錯誤通常出現(xiàn)在使用delegate的時候,因為delegate通常是一個id泛型,所以編譯的時候不會報錯.所以這個時候要用respondsToSelector方法先判斷一下,然后再進行調(diào)用.或者看是誰去調(diào)用了這個方法,然后看這個類或者對象有沒有這個方法.
4.Repeating NSTimer
如果一個Timer是不停repeat,那么釋放之前就應(yīng)該先invalidate.非repeat的timer在fired的時候會自動調(diào)用invalidate,但是repeat的不會.這時如果釋放了timer,而timer其實還會回調(diào).回調(diào)的時候找不到對象就會掛掉.
原因
NSTimer是通過RunLoop來實現(xiàn)定時調(diào)用的,當你創(chuàng)建一個Timer的時候,RunLoop來實現(xiàn)定時調(diào)用的,當你創(chuàng)建一個Timer的時候,RunLoop會持有這個Timer的強引用.如果你創(chuàng)建了一個repeating timer,在下一次回調(diào)前就把這個timer release了, 那么runloop回調(diào)的時候就會找不到對象而crash
寫一個宏來釋放Timer
判斷這個Timer不為nil則停止釋放
define INVALIDATE_TIME(timer) {
if(timer != nil) {
[timer invalidate];
[timer release];
timer = nil;
}
}