前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >iOS 多个category同时交换同一个方法

iOS 多个category同时交换同一个方法

作者头像
且行且珍惜_iOS
发布2021-09-07 16:47:42
1.2K0
发布2021-09-07 16:47:42
举报

1.问题

问题1:同一个类多个category有相同的方法,是如何执行?有没有例外?

文件顺序

结论: 1.结果会覆盖,后面的会覆盖前面的,最后执行的是2的方法。无论是类方法还是实例方法。后面代码会做验证。 2.每个category的+ (void)load方法是独立,都会执行,不会相互覆盖。

问题2:同一个类多个category同时交换一个方法,执行顺序如何?(包括交换后方法同名,交换后方法不同名)

结论: 1.如果交换后方法同名,最后只运行类中的方法 2.如果交换后方法不同名,会倒叙执行文件的方法,如上:先执行2->1->宿主类

2.代码

2.1 RuntimeViewController代码

#import "RuntimeViewController.h"
#import "RuntimeViewController+ExchangeMethod1.h"
#import "RuntimeViewController+ExchangeMethod2.h"

@interface RuntimeViewController ()

@end

@implementation RuntimeViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    [RuntimeViewController runtimeLog];
}

- (void)viewWillAppear:(BOOL)animated{
    [super viewWillAppear:animated];
    NSLog(@"viewWillAppear_原生的");
}

- (void)viewWillDisappear:(BOOL)animated{
    [super viewWillDisappear:animated];
    NSLog(@"viewWillDisappear_原生的");
}

- (void)viewDidAppear:(BOOL)animated{
    [super viewDidAppear:animated];
    NSLog(@"viewWillDisappear_原生的");
}

+ (void)runtimeLog{
    NSLog(@"RuntimeViewController");
}

@end

2.2RuntimeViewController+ExchangeMethod1代码

#import "RuntimeViewController+ExchangeMethod1.h"

@implementation RuntimeViewController (ExchangeMethod1)

+ (void)load{
    NSLog(@"RuntimeViewController load1");
    [self exchangeInstanceMethod1:@selector(viewWillAppear:) method2:@selector(wp_viewWillAppear:)];
    [self exchangeInstanceMethod1:@selector(viewWillDisappear:) method2:@selector(wp_viewWillDisappear1:)];
}

+ (void)exchangeInstanceMethod1:(SEL)method1 method2:(SEL)method2
{
    method_exchangeImplementations(class_getInstanceMethod(self, method1), class_getInstanceMethod(self, method2));
}
- (void)wp_viewWillAppear:(BOOL)animated{
    NSLog(@"viewWillAppear_ExchangeMethod1");
    [self wp_viewWillAppear:animated];
}

- (void)wp_viewWillDisappear1:(BOOL)animated{
    NSLog(@"viewWillDisappear_ExchangeMethod1");
    [self wp_viewWillDisappear1:animated];
}
//直接覆盖
- (void)viewDidAppear:(BOOL)animated{
    [super viewDidAppear:animated];
    NSLog(@"viewDidAppear_ExchangeMethod1");
}

+ (void)runtimeLog{
    NSLog(@"RuntimeViewController1");
}

@end

2.3RuntimeViewController+ExchangeMethod2代码

#import "RuntimeViewController+ExchangeMethod2.h"

@implementation RuntimeViewController (ExchangeMethod2)

+ (void)load{
    NSLog(@"RuntimeViewController load2");
    
    [self exchangeInstanceMethod1:@selector(viewWillAppear:) method2:@selector(wp_viewWillAppear:)];
    [self exchangeInstanceMethod1:@selector(viewWillDisappear:) method2:@selector(wp_viewWillDisappear2:)];
}

+ (void)exchangeInstanceMethod1:(SEL)method1 method2:(SEL)method2
{
    method_exchangeImplementations(class_getInstanceMethod(self, method1), class_getInstanceMethod(self, method2));
}
- (void)wp_viewWillAppear:(BOOL)animated{
    NSLog(@"viewWillAppear_ExchangeMethod2");
    [self wp_viewWillAppear:animated];
}

- (void)wp_viewWillDisappear2:(BOOL)animated{
    NSLog(@"viewWillDisappear_ExchangeMethod2");
    [self wp_viewWillDisappear2:animated];
}

//直接覆盖
- (void)viewDidAppear:(BOOL)animated{
    [super viewDidAppear:animated];
    NSLog(@"viewDidAppear_ExchangeMethod2");
}

+ (void)runtimeLog{
    NSLog(@"RuntimeViewController2");
}

@end

3.结果

3.1 runtimeLog与viewDidAppear测试类方法与实例方法会相互覆盖

控制台日志: RuntimeViewController2 viewDidAppear_ExchangeMethod2

此日志说明category的方法会覆盖宿主类的方法,而多个category类方法与实例方法都会相互覆盖,后面的文件覆盖前面的文件。

3.2 load中的NSLog测试load方法都会执行,方法交换都会生效

控制台日志: RuntimeViewController load1 RuntimeViewController load2

此日志说明load不会相互覆盖

3.3 viewWillAppear验证交换后方法同名结果

控制台日志: viewWillAppear_原生的

此日志说明:多个category同时交换同一个方法,且交换后的方法名称也相同,结果等同于没有交换。 原因很简单:ExchangeMethod1交换后,ExchangeMethod2又交换回去了,相当于没有交换。如果新建ExchangeMethod3,你会发现还是有交换的。

3.4 viewWillDisappear验证交换后方法不同名结果

控制台日志: viewWillDisappear_ExchangeMethod2 viewWillDisappear_ExchangeMethod1 viewWillDisappear_原生的

此日志说明:多个category同时交换同一个方法,交换后的方法名称不相同。如果交换后方法不同名,会倒叙执行文件的方法,如上:先执行2->1->宿主类

3.5 验证3.4交换后的关系

  1. 假设有1,2,3分别代表:类、category1,category2.
  2. category1中方法交换

第一步交换

  1. 3与2交换,由于第一步2与1交换了,相当于3与1交换,即3指向了1指向的方法

第二步第一次交换

  1. 3与2交换,相当于是与1交换,即1指向了3

第二步交换完成

执行的顺序:3->2->1 1.首先调用的是类(1)中的方法,相当于调用了3 2.3调了本身方法,即调用了2方法 3.2再调了本身方法,即调了1方法 4.最后打印1中的日志

理解了1,2,3的顺序,对号入座即可。

顺序

由此验证了 3.4 的打印结果。

总结: 为什么要研究这个问题呢?在使用MJRefresh与FDTemplateLayoutCell框架时,发现同时交换了reloadData方法。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2019-11-4 1,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1.问题
    • 问题1:同一个类多个category有相同的方法,是如何执行?有没有例外?
      • 问题2:同一个类多个category同时交换一个方法,执行顺序如何?(包括交换后方法同名,交换后方法不同名)
      • 2.代码
        • 2.1 RuntimeViewController代码
          • 2.2RuntimeViewController+ExchangeMethod1代码
            • 2.3RuntimeViewController+ExchangeMethod2代码
            • 3.结果
              • 3.1 runtimeLog与viewDidAppear测试类方法与实例方法会相互覆盖
                • 3.2 load中的NSLog测试load方法都会执行,方法交换都会生效
                  • 3.3 viewWillAppear验证交换后方法同名结果
                    • 3.4 viewWillDisappear验证交换后方法不同名结果
                      • 3.5 验证3.4交换后的关系
                      领券
                      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档