OC 基于Runtime Swizzle 机制实现检测内存

题记:疫情无情 人有情 人间值得

实现思路:

NSObject+Swizzle 实现方法交换;UIViewController+hook实现将viewController生命周期方法交换;UINavigationController+hook实现popViewController交换.

实现过程如下

NSObject+Swizzle.h 中申明

+ (void)swizzleMethod:(SEL)originalSEL swizzleSelector:(SEL)SwizzleSEL;

NSObject+Swizzle.m 中实现方法交换

+ (void)swizzleMethod:(SEL)originalSEL swizzleSelector:(SEL)SwizzleSEL{

    Class class = [self class];

    Method originalMthod = class_getInstanceMethod(class, originalSEL);

    Method swizzleMethod = class_getInstanceMethod(class, SwizzleSEL);

    IMP originalIMP = method_getImplementation(originalMthod);

    IMP swizzleIMP = method_getImplementation(swizzleMethod);

    //是否t添加成功g方法:添加了原始方法 实现内容指向目标方法

    BOOL isAdd = class_addMethod(class, originalSEL, swizzleIMP, method_getTypeEncoding(swizzleMethod));

    if (isAdd) {

        //初始化指向目标,那么把目标的内容指向初始

        class_replaceMethod(class, SwizzleSEL, originalIMP, method_getTypeEncoding(originalMthod));

    }else{

        //没有添加成功说明已经存在,就交换

        //注意这里交换实现的是IMP 交换

        method_exchangeImplementations(originalMthod, swizzleMethod);

    }

}

UIViewController+hook.m 中

+(void)load{

    static dispatch_once_t onceToken;

    dispatch_once(&onceToken, ^{

        [self swizzleMethod:@selector(viewWillAppear:) swizzleSelector:@selector(lg_viewWillAppear:)];

        [self swizzleMethod:@selector(viewDidDisappear:) swizzleSelector:@selector(lg_viewDidDisappear:)];

    });

}

增加一个场字符串popFlag变量 用以标记视图控制器pop状态

const char  *popFlag = "popFlag";

lg_viewWillAppear方法中 运行时增加一个BOOL变量默认赋值为NO

- (void)lg_viewWillAppear:(BOOL)animated{

    [self lg_viewWillAppear:animated];

      objc_setAssociatedObject(self, popFlag, @(NO), OBJC_ASSOCIATION_ASSIGN);

}

lg_viewDidDisappear方法中 判断BOOL变量 是否为YES 如果为YES 就开启内存检测

- (void)lg_viewDidDisappear:(BOOL)animated{

    [self lg_viewWillAppear:animated];

    if ([objc_getAssociatedObject(self, popFlag) boolValue]) {

        [self lg_dealloc];

    }

}

- (void)lg_dealloc{

    __weak typeof(self) weakSelf = self;

    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{

        __strong typeof (self) strongSelf = weakSelf;

        NSLog(@"lg_dealloc----%@",strongSelf);

    });

}

UINavigationController+hook.m中

+ (void)load{

    static dispatch_once_t onceToken;

    dispatch_once(&onceToken, ^{

        [self swizzleMethod:@selector(popViewControllerAnimated:) swizzleSelector:@selector(lg_popViewControllerAnimated:)];

    });

}

- (UIViewController *)lg_popViewControllerAnimated:(BOOL)animated{

    UIViewController *popVC = [self lg_popViewControllerAnimated:animated];

    //导入外部变量

    extern const char  *popFlag ;

    objc_setAssociatedObject(popVC, popFlag, @(YES), OBJC_ASSOCIATION_ASSIGN);

    return  popVC;

}

四个典型的直接使用 Runtime 方法进行方法交换的风险。我稍作整理,以方便你查看,并便于你理解后续的内容。

第一个风险是,需要在 +load 方法中进行方法交换。因为如果在其他时候进行方法交换,难以保证另外一个线程中不会同时调用被交换的方法,从而导致程序不能按预期执行。

第二个风险是,被交换的方法必须是当前类的方法,不能是父类的方法,直接把父类的实现拷贝过来不会起作用。父类的方法必须在调用的时候使用,而不是方法交换时使用。

第三个风险是,交换的方法如果依赖了 cmd,那么交换后,如果 cmd 发生了变化,就会出现各种奇怪问题,而且这些问题还很难排查。特别是交换了系统方法,你无法保证系统方法内部是否依赖了 cmd。

第四个风险是,方法交换命名冲突。如果出现冲突,可能会导致方法交换失败。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
毕业设计,基于SpringBoot+Vue+MySQL开发的影城管理系统,源码+数据库+论文答辩+毕业论文+视频演示 随着现在网络的快速发展,网上管理系统也逐渐快速发展起来,网上管理模式很快融入到了许多生活之中,随之就产生了“小徐影城管理系统”,这样就让小徐影城管理系统更加方便简单。 对于本小徐影城管理系统的设计来说,系统开发主要是采用java语言技术,在整个系统的设计中应用MySQL数据库来完成数据存储,具体根据小徐影城管理系统的现状来进行开发的,具体根据现实的需求来实现小徐影城管理系统网络化的管理,各类信息有序地进行存储,进入小徐影城管理系统页面之后,方可开始操作主控界面,主要功能包括管理员:首页、个人中心、用户管理、电影类型管理、放映厅管理、电影信息管理、购票统计管理、系统管理、订单管理,用户前台;首页、电影信息、电影资讯、个人中心、后台管理、在线客服等功能。 本论文主要讲述了小徐影城管理系统开发背景,该系统它主要是对需求分析和功能需求做了介绍,并且对系统做了详细的测试和总结。具体从业务流程、数据库设计和系统结构等多方面的问题。望能利用先进的计算机技术和网络技术来改变目前的小徐影城管理系统状况,提高管理效率。 关键词:小徐影城管理系统;Spring Boot框架,MySQL数据库
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值