美文网首页
利用runtime来实现一个数组防崩溃替换

利用runtime来实现一个数组防崩溃替换

作者: Isy | 来源:发表于2016-06-30 21:48 被阅读291次

    前言

    很多时候,我们常常在使用数组的时候因为数组越界而导致程序崩溃。我们通过runtime中的特殊手段,实现在运行时互换函数,达到偷天换日效果。

    Method Swizzling

    Method Swizzling是发生在运行时期的,主要是在运行时,将两个Method交换。达到偷天换日的效果,Method Swizzling是面向切面编程的一种技术。

    OBJC_EXPORT void method_exchangeImplementations(Method m1, Method m2) 
     __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
    
    #import <Foundation/Foundation.h>
    /**
     *  不可变数组防越界崩溃处理
     */
    @interface NSArray (AXKArray)
    
    @end
    
    #import "NSArray+AXKArray.h"
    #import <objc/runtime.h>
    
    @implementation NSArray (AXKArray)
    
    + (void)load
    {
        [super load];
        Method originalMethod = class_getInstanceMethod(objc_getClass("__NSArrayI"), @selector(objectAtIndex:));
        Method userMethod = class_getInstanceMethod(objc_getClass("__NSArrayI"), @selector(axk_objectAtIndex:));
        if (!class_addMethod(objc_getClass("__NSArrayI"), @selector(objectAtIndex:), method_getImplementation(userMethod), method_getTypeEncoding(userMethod))) {
             method_exchangeImplementations(originalMethod, userMethod);
        }
    }
    - (id)axk_objectAtIndex:(NSUInteger)index
    {
        if (self.count - 1 < index) {
            //异常处理,捕获异常并抛出异
            @try {
                return [self axk_objectAtIndex:index];
            }
            @catch (NSException *exception) {
                NSLog(@"不可变数组越界访问异常--%s--Crash Because Method--%s---以上异常", class_getName(self.class), __func__);
                NSLog(@"异常下标--%lu--", index);
                NSLog(@"不可变数组越界访问异常日志%@", [exception callStackSymbols]);
                return nil;
            }
            @finally {
                
            }
        } else {
            return [self axk_objectAtIndex:index];
        }
    }
    @end
    

    类簇、替身、真身

    在iOS中存在大量的有关类簇、真身、替身相关的类等

    大家发现了吗,__NSArrayI才是NSArray真正的类,而NSMutableArray又不一样。我们可以通过runtime函数获取真正的类:

    objc_getClass("__NSArrayI")
    下面我们列举一些常用的类簇的“真身”:

    真身
    NSArray __NSArrayI
    NSMutableArray __NSArrayM
    NSDictionary __NSDictionaryI
    NSMutableDictionary __NSDictionaryM

    Method Swizzling方法只能对替身的真身有效,对替身没有效果。

    相关文章

      网友评论

          本文标题:利用runtime来实现一个数组防崩溃替换

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