美文网首页iOS底层原理
runtime解决数组和字典越界或存nil造成的crash

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

作者: gly333 | 来源:发表于2017-05-02 18:04 被阅读438次

    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 图8 图9

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

    方法:

    图10

    实现:

    图11

    NSMutableArray 

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

    图12

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

    NSDictionary

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

    图13

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

    图14

    NSMutableDictionary

    __NSDictionaryM也只操作增删改查。

    增:

    图15

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

    图16

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

    删:

    图17

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

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

    Demo

    相关文章

      网友评论

      • 刘超_a594:你好,arr[] 这种取值好像还是会崩
        刘超_a594:@gly333 后来发现一直崩在这里 就加了这个方法置换,不过还是很虚 ,毕竟只是仿照你的做的,不太懂原理
        gly333:@刘超_a594 试了一下确实是,给这个方法加个判断就可以了objectAtIndexedSubscript

      本文标题:runtime解决数组和字典越界或存nil造成的crash

      本文链接:https://www.haomeiwen.com/subject/igbnmttx.html