iOS - Method Swizzling

ops/2025/1/13 17:30:51/

让我详细总结一下 Method Swizzling 的使用和注意事项:

1. 基本实现

// 基本的 Method Swizzling 实现
@implementation UIViewController (Tracking)+ (void)load {static dispatch_once_t onceToken;dispatch_once(&onceToken, ^{// 1. 获取原始方法和替换方法Method originalMethod = class_getInstanceMethod(self, @selector(viewDidAppear:));Method swizzledMethod = class_getInstanceMethod(self, @selector(track_viewDidAppear:));// 2. 尝试添加方法实现BOOL didAddMethod = class_addMethod(self,@selector(viewDidAppear:),method_getImplementation(swizzledMethod),method_getTypeEncoding(swizzledMethod));// 3. 如果添加成功,直接替换实现if (didAddMethod) {class_replaceMethod(self,@selector(track_viewDidAppear:),method_getImplementation(originalMethod),method_getTypeEncoding(originalMethod));} else {// 4. 添加失败,说明方法已存在,直接交换实现method_exchangeImplementations(originalMethod, swizzledMethod);}});
}// 新方法实现
- (void)track_viewDidAppear:(BOOL)animated {// 1. 调用原始实现[self track_viewDidAppear:animated];  // 注意:这里实际会调用原始的 viewDidAppear:// 2. 添加新的功能[self trackViewPageAppear];
}@end

2. 注意事项

2.1 执行时机

// 1. 在 +load 方法中执行
+ (void)load {// 在这里执行 swizzling// 因为 +load 在类加载时调用,比较安全
}// 2. 避免在 +initialize 中执行
+ (void)initialize {// 不要在这里执行 swizzling// 因为 +initialize 可能被调用多次
}

2.2 线程安全

// 使用 dispatch_once 确保只执行一次
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{// swizzling 代码
});

2.3 方法命名

// 使用清晰的前缀避免命名冲突
- (void)xyz_swizzledMethod {// 新的实现
}// 避免使用
- (void)swizzledMethod {  // 可能造成命名冲突
}

2.4 子类处理

// 检查当前类是否真正实现了该方法
+ (void)swizzleMethod:(SEL)originalSelector {Class class = [self class];// 确保方法存在于当前类,而不是继承自父类Method originalMethod = class_getInstanceMethod(class, originalSelector);if (method_getImplementation(originalMethod) == method_getImplementation(class_getInstanceMethod([NSObject class], originalSelector))) {return;  // 方法来自基类,不进行 swizzling}// 进行 swizzling
}

2.5 方法签名

// 确保方法签名匹配
- (void)swizzled_method:(id)arg1 withObject:(id)arg2 {// 参数类型和数量必须与原方法完全匹配
}

3. 常见陷阱

3.1 递归调用

// 错误示例
- (void)swizzled_method {[self swizzled_method];  // 死循环!
}// 正确示例
- (void)swizzled_method {// 在 swizzling 后,这里会调用原始实现[self swizzled_method];  // 添加新功能
}

3.2 父类方法

// 避免重复 swizzling
static BOOL isSwizzled = NO;+ (void)load {if (!isSwizzled) {// 执行 swizzlingisSwizzled = YES;}
}

4. 最佳实践

4.1 封装 Swizzling

@implementation NSObject (Swizzling)+ (BOOL)swizzleMethod:(SEL)origSel withMethod:(SEL)altSel {Method origMethod = class_getInstanceMethod(self, origSel);Method altMethod = class_getInstanceMethod(self, altSel);if (!origMethod || !altMethod) {return NO;}class_addMethod(self,origSel,class_getMethodImplementation(self, origSel),method_getTypeEncoding(origMethod));class_addMethod(self,altSel,class_getMethodImplementation(self, altSel),method_getTypeEncoding(altMethod));method_exchangeImplementations(class_getInstanceMethod(self, origSel),class_getInstanceMethod(self, altSel));return YES;
}@end

4.2 文档化

// 清晰的文档说明
/*** 替换 viewDidAppear: 方法用于追踪页面显示* 警告:此方法会影响所有 UIViewController 实例* 在 +load 方法中调用,确保在应用启动时完成替换*/
+ (void)swizzleViewDidAppear {// swizzling 实现
}

总结:

  1. 在 +load 中执行
  2. 使用 dispatch_once
  3. 检查方法存在性
  4. 正确处理方法签名
  5. 避免递归调用
  6. 注意子类影响
  7. 清晰的命名约定
  8. 完善的文档说明

Method Swizzling 是一个强大但危险的特性,需要谨慎使用。


http://www.ppmy.cn/ops/149776.html

相关文章

易语言文字识别OCR

一.引言 文字识别,也称为光学字符识别(Optical Character Recognition, OCR),是一种将不同形式的文档(如扫描的纸质文档、PDF文件或数字相机拍摄的图片)中的文字转换成可编辑和可搜索的数据的技术。随着技…

Django Admin 中实现 ECS 服务重启的细粒度权限控制

在管理大型分布式系统时,对不同服务的重启权限进行精细控制是非常重要的。本文将介绍如何在 Django Admin 中实现对 ECS(Elastic Container Service)服务重启的细粒度权限控制。 背景 假设我们有一个管理 ECS 服务的 Django 应用。我们需要允许不同的管理员重启不同的 ECS…

mac homebrew配置使用

本文介绍mac上homebrew工具的安装、配置过程。homebrew功能类似于centos的yum,用于软件包的管理,使用上有命令的差异。 本次配置过程使用mac,看官方文档,在linux上也可以用,但我没试过,有兴趣的同学可以试试…

【2024年华为OD机试】(B卷,100分)- 组成最大数 (Java JS PythonC/C++)

一、问题描述 题目描述 小组中每位都有一张卡片,卡片上是6位内的正整数,将卡片连起来可以组成多种数字,计算组成的最大数字。 输入描述 “,”号分割的多个正整数字符串,不需要考虑非数字异常情况,小组最多25个人。…

基于ADMM交替方向乘子法的超大规模储备系统分布式协同优化算法收敛性matlab仿真与分析

目录 1.课题概述 2.系统仿真结果 3.核心程序与模型 4.系统原理简介 5.完整工程文件 1.课题概述 基于ADMM交替方向乘子法的超大规模储备系统分布式协同优化算法收敛性matlab仿真与分析。为了验证算法在超大规模储能系统中应用的可行性,在一个由10/21个子储能系统…

免费开源的下载工具Xdown

软件介绍 Xdown是一款功能强大的开源免费下载工具,专为PC端用户设计,支持多种协议和下载方式。 1、多线程下载 Xdown支持最高128线程的并发下载,能够将文件分割成多个部分同时下载,从而显著提升下载速度。 2、多种协议支持 该…

Ubuntu 22.04 桥接配置

1. 网卡配置文件备份 sudo cp /etc/netplan/01-network-manager-all.yaml /etc/netplan/01-network-manager-all.yaml.bak 1.1 静态ip配置 1.1.3 解释 network: version: 2 ethernets: # 网卡名称 使用ifconfig查看 ens33: dhcp4: false dhcp6: false …

2024年12月 Scratch 图形化(四级)真题解析#中国电子学会#全国青少年软件编程等级考试

Scratch图形化等级考试(1~4级)全部真题・点这里 一、选择题(共10题,共30分) 第 1 题 列表存放全班同学的身高,小猫运行下列程序,下列选项说法正确的是?( ) A. 程序会计算出全班身高的最高值 B. 程序会计算出全班身高的最低值 C. 程序会计算出全班身高的平均值 D. …