runtime解决数组和字典越界或存nil造成的crash

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. 

大意是指定初始化方法通常会有很多参数,为了方便有了间接初始化方法,只提供需要的参数,间接初始化方法最后都会通过指定初始化方法来初始化对象。如下图

图1

直奔主题

NSArray 

大家都知道数组和字典都属于类簇是由工厂方法抽象出来的类,其中NSArray 大概有以下几类具体类:

__NSPlaceholderArray ,__NSArray0,__NSSingleObjectArrayI,__NSArrayI 如下图

图2

其中__NSPlaceholderArray是只alloc而没有初始化,而其它三个都是不同的初始化而来

1.存nil造成crash

不可变数组因不可变所以只有通过指定初始化来赋值,如图

图3

所以直接操作此方法即可

图4
图5

这里用__NSPlaceholderArray是因为对象先alloc再调用初始化,而alloc会生成__NSPlaceholderArray

2.越界

上图

图6
图7
runtime解决数组和字典越界或存nil造成的crash_第1张图片
图8
runtime解决数组和字典越界或存nil造成的crash_第2张图片
图9

发现都会调用objectAtIndex:方法 只是调用类是NSArray的具体类,所以这里分别对具体类操作objectAtIndex:即可:

方法:

图10

实现:

runtime解决数组和字典越界或存nil造成的crash_第3张图片
图11

NSMutableArray 

__NSArrayM大概只操作以下方法即可

图12

具体实现就不写了,有兴趣的去下载Demo

NSDictionary

NSArray一样,只操作指定初始化方法即可,如图

图13

还有一个需要注意的是NSDictionary可以通过-setValue:forKey:方法来修改value,此方法的value可以为nil,但是key不可以为nil 并且key不能是NSDictionary原有key以外的值。此方法是NSObject的方法,这里就不修改了,如果想修改应放到NSObject类别中,这些子类自然可以调用。

runtime解决数组和字典越界或存nil造成的crash_第4张图片
图14

NSMutableDictionary

__NSDictionaryM也只操作增删改查。

增:

图15

还有一点需要了解一下当调用- setObject:forKeyedSubscript:-setValue: forKeyPath:方法时 会调用 如下方法

图16

当值参数为nil时则会调用-removeObjectForkey:方法,当key也是nil时则crash,这里remove的修改会放在删的模块里。

删:

图17

改和增的方法一样,查key可以为nil

小记到此为止了,当然 还有NSSet等类簇也同字典数组一样,只是不常用,有时间整理还不如用的时候小心一些呢,如有不足,请大家指出,共同学习。

Demo

你可能感兴趣的:(runtime解决数组和字典越界或存nil造成的crash)