runtime交换方法的正确姿势

2023-11-16

runtime交换方法的正确姿势

说到Objective-C大家就会想到黑魔法runtime,(不知道runtime是什么的看这里,runtime是开源的,源码在这里),本文主要讲解如何利用runtime正确的交换方法,将会提到两种方式去交换,以及我们在什么情况下改怎么去用。

我们知道OC的方法到了runtime就被体现成结构体

struct objc_method {
    SEL method_name                                          OBJC2_UNAVAILABLE;
    char *method_types                                       OBJC2_UNAVAILABLE;
    IMP method_imp                                           OBJC2_UNAVAILABLE;
}

要交换方法的话,无非也就是下面两个方法:

OBJC_EXPORT IMP method_setImplementation(Method m, IMP imp) 
    OBJC_AVAILABLE(10.5, 2.0, 9.0, 1.0);
OBJC_EXPORT void method_exchangeImplementations(Method m1, Method m2) 
    OBJC_AVAILABLE(10.5, 2.0, 9.0, 1.0);

我们通常同的估计也就是第二种方法吧,下面我们来看看用第二种方法存在什么样的问题,我们假设有这么两个方法:

Method m1 { 

      SEL method_name = @selector(originalMethodName)
      char *method_types = “v@:“ //returns void, params id(self),selector(_cmd)
      IMP method_imp = 0x000FFFF (MyBundle`[MyClass originalMethodName])
 }

Method m2 { 

       SEL method_name = @selector(swizzle_originalMethodName)
       char *method_types = “v@:”
       IMP method_imp = 0x1234AABA (MyBundle`[MyClass swizzle_originalMethodName])
 }

我们方法实现如下,在交换的方法里面调用原来的方法:

   - (void) originalMethodName //m1
     {
     }
     - (void) swizzle_originalMethodName //m2
     {
            [self swizzle_originalMethodName];//call original method
     }

那么这两个方法看起来就是这样的:

Method m1 { 

     SEL method_name = @selector(originalMethodName)
     char *method_types = “v@:“ //returns void, params id(self),selector(_cmd)
     IMP method_imp = 0x1234AABA (MyBundle`[MyClass swizzle_originalMethodName])
 }

Method m2 {

     SEL method_name = @selector(swizzle_originalMethodName)
     char *method_types = “v@:”
     IMP method_imp = 0x000FFFF (MyBundle`[MyClass originalMethodName])
 }

那么问题就来了,因为这样导致_cmd改变了,要是原来的方法根据_cmd做了操作的话(原方法实现一般都是看不到的),这时候就会出事了:

- (void) originalMethodName //m1
 {
          assert([NSStringFromSelector(_cmd) isEqualToString:@“originalMethodNamed”]);
 }

那么我们在看看OBJC_EXPORT IMP method_setImplementation(Method m, IMP imp)
OBJC_AVAILABLE(10.5, 2.0, 9.0, 1.0);这个方法来交换方法,该方法调用之后会返回原方法的实现,知道上面的问题之后,我们最好的交换方式就是用一个C语言函数实现去替换原方法实现,C函数大概长这样的:

void __Swizzle_OriginalMethodName(id self, SEL _cmd)
 {
//调用原方法
originalImp(self,_cmd);
//code
 }

那么我们下面的代码可能长这样:

IMP swizzleImp = (IMP)__Swizzle_OriginalMethodName;
IMP originalImp = method_setImplementation(method,swizzleImp);

拿这两个方法来说,主要就是防止人家的代码里面根据selector参数去做了操作而出现问题,这种情况多出现在你的代码用作三方等,要是自己项目的话,还是随便写的,不过说回来,要是苹果的方法里面这样用了,那么我们就不能用OBJC_EXPORT void method_exchangeImplementations(Method m1, Method m2)
OBJC_AVAILABLE(10.5, 2.0, 9.0, 1.0);交换哦


还是那句话,如您发现任何错误,欢迎留言指正~

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

runtime交换方法的正确姿势 的相关文章

  • 如何呈现半屏模态视图?

    我有一个 UIViewController 当按下按钮时 我想要一个半屏视图向上滑动 其中有一个 UIPicker 我在 IB 中使用 UIPicker 和带有 完成 取消 按钮的 UIToolBar 制作了一个 UIView 我怎样才能做
  • 将 iCloud 存储迁移到本地存储并确保每次应用程序启动时数据都在那里

    基于这里的问题 将 iCloud 数据迁移到本地存储并阻止 iCloud 继续响应 https stackoverflow com questions 25186787 migrate icloud data to local store
  • 图像高斯模糊 - iOS 8

    我有一个移动的背景图像 我想模糊它的底部 我would只用 Photoshop 就能做到 但由于图像会移动 效果不太好 这就是我的意思 看图片底部 基本上就像底座对 iPhone 的影响一样 我使用的是 iOS 8 但不是 Swift 我根
  • 使用 iOS 7 检索设备 WiFi MAC 地址

    我们的应用程序使用设备 WiFi MAC 地址来唯一标识设备 根据苹果文档 https developer apple com news id 8222013a我们将开始使用 UIDevice 的identifierForVendor 属性
  • 如何将 UIPopoverPresentationController 的高度设置为与 UITableView 相同

    我在我的应用程序上使用 UIPopoverPresentationController 在我的 iPhone 上显示弹出窗口 使用 UIModalPresentationNone 我希望尺寸随着 UITableView 的高度而动态变化 但
  • iPad 2 检测

    由于我没有 iPad 2 因此我需要知道调用 UIDevice currentDevice model 时它返回什么 我以为它只返回 iPad 但看来我错了 有人可以告诉我吗 Thanks 检查是否有带摄像头的 iPad BOOL isIP
  • 我如何在 viewDidLoad 中执行 UIView animateWithDuration ? IOS 7

    我在 viewDidAppear 中尝试这个 但我有一秒钟的延迟 我能做什么 在 viewDidLoad 中工作 void viewDidAppear BOOL animated fullRotation CABasicAnimation
  • 在完成块中保留循环

    在我的课堂上 我创建了这个方法 void refreshDatasourceWithSuccess CreateDataSourceSuccessBlock successBlock failure CreateDataSourceFail
  • 如何在 UITableView 中显示零行的表格

    我正在动态地将内容加载到 UITableView 中 如果有数据 表格需要显示数据 如果没有数据 表格应显示普通页面 但在我的应用程序中 表格显示带有两条分隔线的普通页面 我需要删除此分隔线并显示纯白色页面 请建议 任何帮助 将不胜感激 如
  • NSCFData isRessized 崩溃?

    我目前在控制台中收到此崩溃日志 2011 08 23 19 18 40 064 App 1697 707 NSCFData isResizable unrecognized selector sent to instance 0x11f1c
  • UITableView:显示 tableFooterView 时运行代码?

    我正在使用 UIView表页脚视图 http developer apple com library ios documentation uikit reference UITableView Class Reference Referen
  • NSString stringWithContentsOfFile 失败,错误代码似乎错误

    我正在尝试将文件加载到字符串中 这是我正在使用的代码 NSError error nil NSString fullPath NSBundle mainBundle pathForResource filename ofType html
  • NSUInteger 的奇怪行为 - 无法正确转换为浮动

    这是我的情况 这让我发疯 我有一个计数值为 517 的 NSMutableArray 我有一个双精度值 它是我的乘数 double multiplier 0 1223 double result myArray count multipli
  • 生成具有固定数字长度的随机数?

    我正在生成随机数 int randomID arc4random 3000 但我想生成至少 4 位数字的随机数 如 1000 2400 1122 我想知道 Objective C 的代码 请尝试 生成数字 1000 9999 int ran
  • CALayer边框奇怪问题

    我正在向 CALayer 添加边框 但有一些奇怪的行为 在我应用的边框之后出现模糊边框 参见屏幕截图 这是我的代码 void configureLabel self hidden YES self textAlignment NSTextA
  • 如何在没有 SDK 的情况下在 Objective C 中为 S3 创建预签名 URL?

    我正在构建一个 mac 应用程序not使用 AWS iOS 开发工具包 我尝试构建的 GET 请求应遵循以下通用格式 Authorization AWS AWSAccessKeyId base64 hmac sha1 VERB n CONT
  • 调整 UIImage 的大小而不将其完全加载到内存中?

    我正在开发一个应用程序 用户可以在其中尝试加载非常非常大的图像 这些图像首先在表格视图中显示为缩略图 我的原始代码会在大图像上崩溃 因此我重写它以首先将图像直接下载到磁盘 是否有一种已知的方法可以调整磁盘上图像的大小 而无需通过以下方式将其
  • “预期的 ';'在 Swift 下的顶级声明符之后”

    我正在尝试将所有颜色设置在一个 Swift 文件中 该文件可以在我的整个应用程序中使用 下面的代码会导致 import Foundation import UIKit class DotColors let tsblueColor UICo
  • UIPickerView selectRow 未按预期工作

    我创建了一个UIPickerView它有两个组件 第一个组件 A 的行数固定为 13 另一个组件 B 的行数可变 具体取决于 A 中选择的行 加载时UIPickerView我调用以下命令 以便我可以在两个组件中默认选择 但是我遇到的问题是只
  • 处理 UICollectionView 中的点击手势

    由于我无法使用任何框架来创建相册 因此我尝试使用 Collection View 创建自己的相册 但我一开始就陷入困境 我的目标是将网络服务中的所有图像显示到我的集合视图中 因为所有图像都已显示 下一步是当有人点击任何单元格时 我可以在新视

随机推荐

  • .NET Core与.NET Framework、Mono之间的关系

    随着微软的 NET开源的推进 现在在 NET的实现上有了三个 NET Framework Mono和 NET Core 经常被问起Mono的稳定性怎么样 后续Mono的前景如何 要回答这个问题就需要搞清楚这三个 NET 实现之间的关系和将来
  • Ubuntu 22.04 配置静态IP

    1 桥接模式 NAT模式 参考博客 虚拟机上网设置 桥接模式 NAT模式 2 interfaces配置文件 interfaces 5 file used by ifup 8 and ifdown 8 auto lo iface lo ine
  • 论文中图片加方框 matlab代码

    转自 http blog csdn net majinlei121 article details 52334171 加方框函数 cpp view plain copy function I rgb DrawRectangle I Left
  • pymysql介绍

    一 数据库介绍 概念 一个存放数据的仓库 这个仓库按照一定的数据结构组织 存放 管理数据 分类 关系型数据库 mysql sql server oracle DB2等 非关系型数据库 redis等 python操作数据库的方式 pymysq
  • 传统制造型企业如何实现数字化转型?

    传统制造企业可以通过采用技术和数据驱动的方法来实现数字化转型 以改善运营 提高效率并在快速发展的行业中保持竞争力 以下是他们可以遵循的步骤和策略 1 评估和战略制定 评估当前状态 首先评估制造流程 技术基础设施和数据管理系统的当前状态 确定
  • XSS攻击绕过过滤方法大全(转)

    XSS攻击绕过过滤方法大全 约100种 文章目录 XSS攻击绕过过滤方法大全 约100种 1 XSS定位器 2 XSS定位器 短 3 无过滤绕过 4 利用多语言进行过滤绕过 5 通过JavaScript命令实现的图片XSS 6 无分号无引号
  • windows用 tree命令查看目录文件夹结构

    windows用 tree命令查看目录文件夹结构 查看帮助 tree help tree dirsfirst filelimit 6 h t dirsfirst 目录优先展示 filelimit 6 文件夹下超过6个文件的将不展开 s 以字
  • 启动mysql服务的时候一直报ERROR! The server quit without updating PID file

    问题背景 最近在电脑的vmware上安装了个CentOS 7系统 并在系统中装了mysql 8 0 11 可是启动服务的时候一直报错 如下 root localhost etc service mysql start Starting My
  • CloudCompare二次开发(1)——获取指定高程的所有点

    目录 一 源码编译 二 制作流程 三 结果展示 本文由CSDN点云侠原创 原文链接 爬虫网站自重 一 源码编译 1 WIN10系统下VS2019编译CloudCompare2 12 4 二 制作流程 1 找到源码中的插件例子 主要支持三种插
  • 类什么时候被加载 java

    创建对象实例时 new 创建子类对象实例 父类也被加载 使用类的静态成员时 静态属性 静态方法
  • 软件工程—软件结构图笔记详谈

    一 定义 结构图 Structure Chart 简称SC图 是精确表达软件结构的图形表示方法 它以特定的符号表示模块 模块间的调用关系和模块间信息的传递 二 主要构成 模块 Module 用矩形框表示 框中写有模块的名字 说明模块的功能
  • 服务器ie浏览器总是未响应,win7电脑IE浏览器总是未响应怎么办 IE浏览器无响应原因解决方法...

    win7电脑IE浏览器总是未响应怎么办 IE浏览器无响应原因解决方法 2016 12 05 已有人学习 编辑 chenwei 来源 电脑技术吧整理 win7电脑IE浏览器总是未响应怎么办 IE浏览器无响应原因解决方法 我们在使用电脑的时候
  • Linux mysql启动失败 Job for mysqld.service failed because the control process exited with error code.

    一 查询mysql无法启动问题 service mysql start 启动mysql 报错 Job for mysqld service failed because the control process exited with err
  • outlook邮箱邮件内容乱码_outlook邮件乱码怎么转换

    造成邮件乱码的原因很多 但归纳起来不外乎有三种情况 一是操作系统和使用的软件设置不同导致的 二是发送邮件时发送程序采用不同的编码标准 如UU MIME BINHEX等 而你所用的操作系统程序没有能力将其解码 收到的邮件像 天书 一般 三是邮
  • 《Graph Neural Networks Foundations,Frontiers and Applications》第一部分第一章第1.2.2节翻译和解读

    书名 Graph Neural Networks Foundations Frontiers and Applications 图神经网络的基础 前沿和应用 出版社 Springer Berlin Heidelberg 作者 Lingfei
  • chatgpt赋能python:Python中如何写π

    Python中如何写 在Python中 写 Pi 即圆周率 可能是一个小小的挑战 但是 这个问题的答案相对比较简单 在本文中 我们将介绍如何在Python中计算 以及如何使用Python的数学库 math库 介绍 是一个十分重要的数学常数
  • 决策树与R语言(RPART)

    关于决策树理论方面的介绍 李航的 统计机器学习 第五章有很好的讲解 传统的ID3和C4 5一般用于分类问题 其中ID3使用信息增益进行特征选择 即递归的选择分类能力最强的特征对数据进行分割 C4 5唯一不同的是使用信息增益比进行特征选择 特
  • 自动寻路算法C语言,C语言实现A*算法

    CopyRight c HYTC Ltd All rights reserved Filename main c Creator GaoLei Version 0 0 Date 2011 06 15 QQ 38929568 Descript
  • 微信小程序中使用svga动画

    参考资料 https github com svga SVGAPlayer Web tree mphttps github com svga SVGAPlayer Web tree mp 也可以参考 我主要参考的上面的 https gith
  • runtime交换方法的正确姿势

    runtime交换方法的正确姿势 说到Objective C大家就会想到黑魔法runtime 不知道runtime是什么的看这里 runtime是开源的 源码在这里 本文主要讲解如何利用runtime正确的交换方法 将会提到两种方式去交换