iOS開發中需要大量對dictionary和array進行操作,因此我們需要一種更加安全可靠的操作方法來避免不必要的crash。當然可以通過自定義dictionary 和array重載增刪改查的方法來避免crash,但是由于許多工程基本成型以后,如此操作的話工作量,改動等都會很大。此時我們可以利用OC語言動態特性對數組和字典的增刪改查方法進行Method Swizzling(不懂得自行百度吧) ,替換成我們經過安全操作的方法,從而進行安全操作。當然有好多大神已經實現過了,但是畢竟會用并不代表是自己的。好了廢話不多說吧,下面我們就開始自己動手一步步實現我們自己的safe類吧。
一. 首先第一步我們需要知道字典和素組進行操作(也支持字面量操作)崩潰的原因有哪些:
-
不可變數組NSArray 常用的方法有
objectAtIndex
objectAtIndexedSubscript
arrayByAddingObject
arrayWithObject
主要的crash reason是數組越界,運行一下代碼
代碼1
程序崩潰 看下日志reason: '*** -[__NSArrayI objectAtIndex:]: index 3 beyond bounds [0 .. 2]
運行下面代碼 數組中追加了一個nil值
代碼2程序崩潰日志
reason: '*** -[NSArray arrayByAddingObject:]: object cannot be nil'
運行代碼
NSArray * testArray = [NSArray arrayWithObject:nil];
崩潰日志reason: '*** -[__NSPlaceholderArray initWithObjects:count:]: attempt to insert nil object from objects[0]
可變數組常用方法 增刪改查等 主要有
1.[__NSPlaceholderArray initWithObjects:count:] 2.[__NSArrayM insertObject:atIndex:] 3.[__NSArrayM objectAtIndex:] 4.[__NSArrayM removeObjectAtIndex:] 5.[__NSArrayM replaceObjectAtIndex:withObject:] 6.[NSMutableArray replaceObjectsInRange:withObjectsFromArray:]
不可變字典 初始化有空值
[__NSPlaceholderDictionary initWithObjects:forKeys:count:]
可變字典常用方法
setObject: forKey:
removeObjectsForKeys:
removeObjectForKey:
進行操作是key value 不能為nil
二. 第二步我們利用runtime在實現load方法( + load 方法,那么當類被加載時它會自動被調用)時將這些方法進行hook,注意方法進行Swizzling時候程序生命周期內只需要執行一次:
對NSArray舉例實現一下
1\.新建NSArray的categary NSArray+Safe
當數組越界時 crash reason[__NSArrayI objectAtIndex:]: index 3 beyond bounds [0 .. 2]
我們需要使用函數method_exchangeImplementations(method1,method2)
交換兩個方法的實現指針 因為交換指針需要多次使用,我們對此方法進行封裝
如下圖:

實現一下load函數
如下圖

實現我們自定義的方法
如下圖

ok,數組越界已經解決了!可以試一下啦!
其他的都是大同小異,下面是我的github地址,將庫拖到工程里邊就可以啦!
博客地址