runtime 网上一大堆,这里不介绍了,利用runtime特性,当数组和字典调用指定的存取方法时,通过runtime填加中间方法来判断参数的合法性来避免造成crash。
写之前先简介一下两个概念:
1.指定初始化(Designated Initializer)The initializer of a class that takes the full complement of initialization parameters is usually the designated initializer. The designated initializer of a subclass must invoke the designated initializer of its superclass by sending a message to super.。
2.间接初始化(Secondary Initializer)The convenience (or secondary) initializers—which can include init—do not call super. Instead they call (through a message to self) the initializer in the series with the next most parameters, supplying a default value for the parameter not passed into it.
大意是指定初始化方法通常会有很多参数,为了方便有了间接初始化方法,只提供需要的参数,间接初始化方法最后都会通过指定初始化方法来初始化对象。如下图
直奔主题
NSArray
大家都知道数组和字典都属于类簇是由工厂方法抽象出来的类,其中NSArray 大概有以下几类具体类:
__NSPlaceholderArray ,__NSArray0,__NSSingleObjectArrayI,__NSArrayI 如下图
其中__NSPlaceholderArray是只alloc而没有初始化,而其它三个都是不同的初始化而来
1.存nil造成crash
不可变数组因不可变所以只有通过指定初始化来赋值,如图
所以直接操作此方法即可
这里用__NSPlaceholderArray是因为对象先alloc再调用初始化,而alloc会生成__NSPlaceholderArray。
2.越界
上图
发现都会调用objectAtIndex:方法 只是调用类是NSArray的具体类,所以这里分别对具体类操作objectAtIndex:即可:
方法:
实现:
NSMutableArray
即__NSArrayM大概只操作以下方法即可
具体实现就不写了,有兴趣的去下载Demo。
NSDictionary
和NSArray一样,只操作指定初始化方法即可,如图
还有一个需要注意的是NSDictionary可以通过-setValue:forKey:方法来修改value,此方法的value可以为nil,但是key不可以为nil 并且key不能是NSDictionary原有key以外的值。此方法是NSObject的方法,这里就不修改了,如果想修改应放到NSObject类别中,这些子类自然可以调用。
NSMutableDictionary
即__NSDictionaryM也只操作增删改查。
增:
还有一点需要了解一下当调用- setObject:forKeyedSubscript:和-setValue: forKeyPath:方法时 会调用 如下方法
当值参数为nil时则会调用-removeObjectForkey:方法,当key也是nil时则crash,这里remove的修改会放在删的模块里。
删:
改和增的方法一样,查key可以为nil。
小记到此为止了,当然 还有NSSet等类簇也同字典数组一样,只是不常用,有时间整理还不如用的时候小心一些呢,如有不足,请大家指出,共同学习。