当前位置: 首页 > wzjs >正文

锦州网站优化中国住房和城乡建设部网站资质查询

锦州网站优化,中国住房和城乡建设部网站资质查询,企业工商信息公示系统,wordpress twig方法交换 什么是Method-SwizzlingMethod-Swizzling 翻译过来就是方法交换,它是 Objective-C 运行时(Runtime)提供的一种动态修改方法实现的机制。它的核心是通过交换两个方法的 IMP(方法实现)来实现功能的动态注入或修…

方法交换

什么是Method-Swizzling

  Method-Swizzling 翻译过来就是方法交换,它是 Objective-C 运行时(Runtime)提供的一种动态修改方法实现的机制。它的核心是通过交换两个方法的 IMP(方法实现)来实现功能的动态注入或修改,常用于 AOP(面向切面编程)、调试、日志统计等场景。

关于runtime

runtime是oc的核心机制,oc语言编程时,许多行为(如方法调用、类结构)在程序运行时才确定。

具体表现在其编程时的动态类型(对象的类型在运行时确定)、动态绑定(方法调用在运行时解析,而非编译时)、动态加载(按需加载类和资源)、消息传递机制(方法调用本质是向对象发送消息(objc_msgSend))。

关于IMP

IMP是 Objective-C 方法的底层实现,本质上是一个指向 C 函数的指针,格式为 id (*)(id, SEL, ...)

每个方法(Method)对应一个 IMP,它决定了方法被调用时的具体行为。

  在之前的学习中,我们可以知道,OC的方法调用通过 objc_msgSend 函数发送消息,运行时根据 SEL(方法名)查找对应的 IMP 并执行。

关于AOP与OOP

AOP主要解决的是横切关注点的问题,也就是那些在多个模块中重复出现的功能,比如日志、安全、事务管理等。这些功能如果分散在各个类中,会导致代码冗余和耦合度高。AOP通过切面(Aspect)将这些横切关注点模块化,从而在编译期或运行时将它们织入到目标代码中。

OOP的核心是类、对象、继承、封装和多态。它通过将数据和行为封装在对象中,利用继承和多态来实现代码的复用和扩展。

这样说可能会比较抽象,我们来举个具体的例子。

假设我们现在需要实现一个电商系统的订单模块,那么其中:

OOP的职责就类似于定义 Order 类,封装订单属性(订单号、金额、状态);实现 OrderService 类,处理订单创建、支付、取消等业务逻辑等。

AOP 的职责就类似于通过切面 LoggingAspect,自动记录订单操作的日志。通过切面 TransactionAspect,为支付方法添加事务管理。通过切面 PermissionAspect,校验用户是否有权限取消订单等。

了解完以上概念之后,我们再回来继续认识Method-Swizzling。

说白了,Method-Swizzling就是在程序运行时将一个方法的实现替换成另一个方法的实现,在OC中,每个类都维护着一个方法列表,即methodList,methodList中有不同的方法,即method,每个方法包含了方法的sel和IMP,方法交换就是将sel和IMP原本的对应断开,并将sel和新的IMP生成对应关系。如下图:

请添加图片描述

方法交换核心API

OC中的Method-Swizzling 依赖于 Runtime 提供的 API,主要用于操作类和方法的实现(IMP)。

因此,我们在使用方法交换相关API之前,要先导入Runtime相关的头文件:

#import "objc/runtime.h"
1. 获取方法对象

通过选择器(SEL)和类获取 Method 结构体,包含方法的实现(IMP)和类型编码(Type Encoding)。

class_getInstanceMethod

Method originalMethod = class_getInstanceMethod([UIViewController class], @selector(viewWillAppear:));

这是一个用于获取类中实例方法的函数,其中第一个参数是获取 UIViewController 类的类对象(Class Object);第二个参数是定义一个方法选择器(SEL),指向 viewWillAppear: 方法。这个函数最终会返回一个Method类型的结构体指针。

这里我们可以找到Method的源码:

typedef struct objc_method *Method;/// Defines a method
struct objc_method_description {SEL _Nullable name; /**< The name of the method *///方法的唯一标识符(通过 @selector(methodName) 生成)。char * _Nullable types; /**< The types of the method arguments *///方法的类型编码字符串(如 "v@:@" 表示返回 void,参数为 id 和 SEL)。
};

class_getClassMethod

Method classMethod = class_getClassMethod([NSArray class], @selector(arrayWithObject:));

这是一个用于获取类方法(Class Method)的函数,参数与返回类型同上。

2. 添加/替换方法实现

用于动态修改类的方法列表。

class_addMethod

BOOL success = class_addMethod([self class], @selector(newMethod), (IMP)newMethodIMP, "v@:");

这个函数用于向类中添加新的方法实现(该方法原不存在)。

  • Class cls:目标类。

  • SEL name:方法选择器。

  • IMP imp:方法实现(C 函数指针)。

  • const char *types:方法类型编码(如 "v@:" 表示返回 void,参数为 idSEL)。

  • 返回值BOOL,表示是否成功添加。

class_replaceMethod

class_replaceMethod([UIViewController class], @selector(viewWillAppear:), (IMP)swizzled_viewWillAppear, "v@:");

若方法存在则替换类的方法实现,若不存在则进行添加。

  • 参数:同 class_addMethod
  • 返回值BOOL,表示是否成功替换或添加。
3. 交换方法实现

直接交换两个方法的 IMP,是 Method-Swizzling 的核心操作。

method_exchangeImplementations

Method originalMethod = class_getInstanceMethod([UIViewController class], @selector(viewWillAppear:));
Method swizzledMethod = class_getInstanceMethod([self class], @selector(swizzled_viewWillAppear:));
method_exchangeImplementations(originalMethod, swizzledMethod);

交换两个 Method 对象的 IMP。

  • 参数Method m1, Method m2
  • 返回值void
4. 获取方法信息

辅助函数,用于提取方法的元数据。

method_getName

SEL selector = method_getName(originalMethod);

获取方法的 SEL。

  • 参数Method m
  • 返回值SEL

method_getTypeEncoding

const char *typeEncoding = method_getTypeEncoding(originalMethod);

获取方法的类型编码(如参数和返回值类型)。

  • 参数Method m
  • 返回值const char *

method_getImplementation

IMP originalIMP = method_getImplementation(originalMethod);

获取方法的 IMP。

  • 参数Method m
  • 返回值IMP
5. 修改方法实现

直接设置方法的 IMP。

method_setImplementation

  • 作用:直接修改方法的 IMP。
  • 参数Method m, IMP imp
  • 返回值IMP(旧实现)。
IMP oldIMP = method_setImplementation(originalMethod, newIMP);

使用示例:完整的 Method-Swizzling 流程

有两种编写方法:一种是写在需要实现方法交换的Category分类文件中;第二种就是写在专门用于 Swizzling 的类中,创建一个 MethodSwizzlingHelper.m 文件,集中管理所有 Swizzling 逻辑。

#import <objc/runtime.h>@implementation UIViewController (Swizzle)+ (void)load {static dispatch_once_t onceToken;dispatch_once(&onceToken, ^{Class class = [self class];SEL originalSelector = @selector(viewWillAppear:);SEL swizzledSelector = @selector(swizzled_viewWillAppear:);Method originalMethod = class_getInstanceMethod(class, originalSelector);Method swizzledMethod = class_getInstanceMethod(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);}});
}- (void)swizzled_viewWillAppear:(BOOL)animated {// 在原始方法前插入逻辑NSLog(@"View will appear: %@", NSStringFromClass([self class]));// 调用原始方法(实际执行交换后的 IMP)[self swizzled_viewWillAppear:animated];
}@end

注意事项

  1. 线程安全:在 +load 中使用 dispatch_once 确保 Swizzling 仅执行一次。
  2. 避免循环调用:在交换后的方法中调用原方法时,必须通过交换后的选择器(如 self.swizzled_viewWillAppear:)。
  3. 方法签名匹配:确保交换的方法参数和返回值类型一致,否则可能导致崩溃。
  4. 影响范围:Swizzling 会影响类及其子类的所有实例,需谨慎操作。

使用方法交换注意事项

线程安全

  mehod-swizzling方法交换一般写在load方法中,而load方法会主动调用多次,这样会导致方法的重复交换,使方法sel的指向又恢复成原来的imp。所以我们需要通过单例模式,使方法交换只执行一次,我们可以通过dispatch_once来实现单例。

方法交换的影响范围

  mehod-swizzling方法交换会影响类及其子类的所有实例。


文章转载自:

http://2VcU1ET6.kkjhj.cn
http://bJuqbet7.kkjhj.cn
http://JRCzPLgB.kkjhj.cn
http://CzOGrD4X.kkjhj.cn
http://iD8lFtwQ.kkjhj.cn
http://XdwDz51G.kkjhj.cn
http://iBoahS0T.kkjhj.cn
http://AFMNq9mm.kkjhj.cn
http://WkS91EzE.kkjhj.cn
http://SItouIHi.kkjhj.cn
http://bwlDwWN6.kkjhj.cn
http://a7IWT16O.kkjhj.cn
http://p9ZpQYf6.kkjhj.cn
http://25OFRbrj.kkjhj.cn
http://GWhAWdBB.kkjhj.cn
http://J664656O.kkjhj.cn
http://qSfLWjRY.kkjhj.cn
http://sB3zbLJK.kkjhj.cn
http://C30LydLk.kkjhj.cn
http://sVLwiUFe.kkjhj.cn
http://9mCFU4qO.kkjhj.cn
http://EmyS7bbr.kkjhj.cn
http://wQtpyIvy.kkjhj.cn
http://dM8N6cwi.kkjhj.cn
http://iRI3qLu6.kkjhj.cn
http://CT9fJg7T.kkjhj.cn
http://bNr0CZBS.kkjhj.cn
http://wo6iN9jB.kkjhj.cn
http://ELjSeskm.kkjhj.cn
http://IfrM0WOb.kkjhj.cn
http://www.dtcms.com/wzjs/651483.html

相关文章:

  • 网站建设需要通过哪些审批网站建设 开发 模板
  • 云南省火电建设公司网站网站网页设计专业公司
  • 整形网站模板wordpress 股票交易
  • 企业微信网站开发中国建设银行电话
  • 网站开发者收入来源wordpress媒体库不显示
  • 怎么注册微网站山西太原建站怎么做
  • 哈尔滨网站建设制作dw怎么做网站地图
  • 如何做网站的图片滑动块一键搭建云免流服务器
  • 最早做网站的那批人群晖WordPress绑定域名
  • 是阿里巴巴好还是自己做网站好?黑龙江网站建设seo优化
  • 北京南站到故宫地铁怎么坐哔哩哔哩免费网站观看
  • 建设工程人才招聘信息网站虚拟主机网站建设过程
  • 百度云做网站有优势吗wordpress排队加载
  • 如何做局域网网站建设网站需要申请什么
  • 岷县城乡建设局网站网络服务商和网络运营商
  • 工业和信息化部五系网站建设宋朝网站应该怎么做
  • 个人怎么交养老保险惠州百度搜索优化
  • 福州做彩票app网站如何建免费的企业网站
  • 网站注册怎么注销wordpress+移动
  • 深圳自适应网站开发多少钱怎么制作网站视频播放器
  • 定西市城乡建设局网站php技术应用于中小企业网站开发
  • 网站策划500字品牌网站设计图片
  • 福州品牌网站设计做调查赚钱的网站
  • 如何制作社交网站网站推广投放
  • phpcms 网站模板site网站连通率0%怎么解决
  • 赣州网站建设培训网站无备案号怎么办
  • 成都市建设工程施工安监站网站wordpress性能优化插件
  • phpcms 怎么做视频网站首页怀化seo优化
  • 百度提交网站珠海公众号开发公司
  • 收款网站怎么建设磁力搜索器 磁力猫在线