runTime(二)应用 Method Swizzling

本文介绍Objective-C中的Method Swizzling技术,通过示例展示了如何利用此技术来减少代码冗余,并提供了一些最佳实践建议。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Method swizzling 就是改变现有selector 所关联的方法的实现。底层原理为,利用runTime更改类底层方法调度表的映射,在完成映射更改后,这样调用既有的selector就会改为调用更改后的方法实现。从而达到方法替换的目的。

在开发中合理的利用Method swizzling可以为我们减少很多冗余的工作。

假设我们想追踪用户在每一个视图控制器的停留时间,不要以为这是一项不必要的工作,恰恰相反这是一批非常有意义的数据(第三方平台友盟为我们提供了相应的后台)。

一个并不复杂的需求,但是我们需要在每一个视图控制器的生命周期函数中加入同样的追踪代码,成吨的冗余代码将会出现在我们的代码中,这并不是一个很好的实现。庆幸的是Method Swizzling可以很好的帮我们解决个麻烦,具体代码如下:

#import <objc/runtime.h>

@implementation UIViewController (Tracking)

+ (
void)load {
   
static dispatch_once_t onceToken;
   
dispatch_once(&onceToken, ^{
        Class class = [
self class];
       
       
SEL originalSelector = @selector(viewWillAppear:);
       
SEL swizzledSelector = @selector(xxx_viewWillAppear:);
       
       
Method originalMethod = class_getInstanceMethod(class, originalSelector);
       
Method swizzledMethod = class_getInstanceMethod(class, swizzledSelector);
       
        // 如果swizzle一个类方法,用下面的方式:
        // Class class = object_getClass((id)self);
       
// ...
       
// Method originalMethod = class_getClassMethod(class, originalSelector);
       
// Method swizzledMethod = class_getClassMethod(class, swizzledSelector);
       
       
BOOL didAddMethod =
       
class_addMethod(class,
                        originalSelector,
                       
method_getImplementation(swizzledMethod),
                       
method_getTypeEncoding(swizzledMethod));
       
       
if (didAddMethod) {
           
class_replaceMethod(class,
                                swizzledSelector,
                               
method_getImplementation(originalMethod),
                               
method_getTypeEncoding(originalMethod));
        }
else {
           
method_exchangeImplementations(originalMethod, swizzledMethod);
        }
    });
}

#pragma mark - Method Swizzling

- (
void)xxx_viewWillAppear:(BOOL)animated {
    [
self xxx_viewWillAppear:animated];
   
NSLog(@"viewWillAppear: %@", self);
}

@end

现在任何一个UIViewController或是他的子类的实例调用到viewWillAppear: 都会去调用xxx_viewWillAppear:的实现,我们也就可以在这里集中处理控制器展示时间的代码。

添加代码到视图控制器生命周期,替换三方库中代码实现,更改底层网络设置等都是很好的应用method swizzling的例子。恰当的使用method swizzling使开发更加高效,但method swizzling是类似于开发中黑魔法的存在,过多的使用会导致代码的晦涩难懂。

无论什么情况下,什么原因使用method swizzling,下面的一些原则是必须要遵守的 

Swizzling 应该写在 +load.
OC中有两个方法会被系统自动调用
+load:在程序启动时加载到该类的时候就会被调用。
+initialize:在程序第一次调用该类 类方法或实例方法时调用

method swizzling是在系统全局产生影响的,所以我们应该在尽可能早的地方实现它。+load在系统加载类的时候就获得了执行。


dispatch_once
method swizzling应该总是被鞋子一个dispatch_once的block中
method swizzling是在系统全局产生影响的,我们必须确保其中的代码只被执行一次哪怕是在不同的线程之中,dispatch_once为我们很好的提供了这个保障。

Invoking _cmd
如下的代码可能会让你感到困惑,这样不会导致死循环么
- (void)xxx_viewWillAppear:(BOOL)animated {
    [
self xxx_viewWillAppear:animated];
    NSLog(@"viewWillAppear: %@", self);
}
是的不会的,事实上正如前面所说,在+load中我们已经完成了Swizzling,当我们调用viewWillAppear:,实际执行的是xxx_viewWillAppear:中的代码,同样的当我们在调用xxx_viewWillAppear:实际执行的是viewWillAppear:中的代码,是不是一种非常微妙的逻辑!!!~



资源下载链接为: https://pan.quark.cn/s/22ca96b7bd39 在当今的软件开发领域,自动化构建与发布是提升开发效率和项目质量的关键环节。Jenkins Pipeline作为一种强大的自动化工具,能够有效助力Java项目的快速构建、测试及部署。本文将详细介绍如何利用Jenkins Pipeline实现Java项目的自动化构建与发布。 Jenkins Pipeline简介 Jenkins Pipeline是运行在Jenkins上的一套工作流框架,它将原本分散在单个或多个节点上独立运行的任务串联起来,实现复杂流程的编排与可视化。它是Jenkins 2.X的核心特性之一,推动了Jenkins从持续集成(CI)向持续交付(CD)及DevOps的转变。 创建Pipeline项目 要使用Jenkins Pipeline自动化构建发布Java项目,首先需要创建Pipeline项目。具体步骤如下: 登录Jenkins,点击“新建项”,选择“Pipeline”。 输入项目名称和描述,点击“确定”。 在Pipeline脚本中定义项目字典、发版脚本和预发布脚本。 编写Pipeline脚本 Pipeline脚本是Jenkins Pipeline的核心,用于定义自动化构建和发布的流程。以下是一个简单的Pipeline脚本示例: 在上述脚本中,定义了四个阶段:Checkout、Build、Push package和Deploy/Rollback。每个阶段都可以根据实际需求进行配置和调整。 通过Jenkins Pipeline自动化构建发布Java项目,可以显著提升开发效率和项目质量。借助Pipeline,我们能够轻松实现自动化构建、测试和部署,从而提高项目的整体质量和可靠性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值