iOS进阶—Runtime基础

2023-10-31

iOS进阶—目录


GitHub参考

RunTime 基础

一个程序的执行过程,大概就是代码->编译链接->执行

C语言

#import <Foundation/Foundation.h>
void run() {
    NSLog(@"%s", __func__);
}
int main(int argc, const char * argv[]) {
    @autoreleasepool {     
        run();  
    }
    return 0;
}

执行结果:

2018-11-16 11:41:34.373347+0800 Runtime001[2263:82588] run
Program ended with exit code: 0

OC 属于消息发送机制,包含SEL 和IMP,如果把OC理解为一本书,SEL (编号)代表书目录的文章标题,IMP(指针)代表文章对应页码,方法实现本身则是正文

Runtime进行同类方法交换

#import <Foundation/Foundation.h>
#import "TZPerson.h"
#import "TZDog.h"
#import <objc/runtime.h>

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        TZPerson* p = [TZPerson new];
        Method m1 = class_getInstanceMethod([p class], @selector(walk));
        Method m2 = class_getInstanceMethod([p class], @selector(run));
        IMP imp = method_getImplementation(m2);
        method_setImplementation(m1, imp);
        [p walk];   
    }
    return 0;
}

执行结果:我们调用的walk,执行的是run方法

2018-11-16 11:49:45.681647+0800 Runtime001[2356:87721] -[TZPerson run]
Program ended with exit code: 0

Method本身是typedef struct objc_method *Method;结构体。我们可以查看Runtime源码(参考GitHub)objc-runtime-master

在这里插入图片描述

上面的代码与下面的代码等价

struct method_t {
    SEL name;
    const char *types;
    IMP imp; 
//    struct SortBySELAddress :
//    public std::binary_function<const method_t&,
//    const method_t&, bool>
//    {
//        bool operator() (const method_t& lhs,
//                         const method_t& rhs)
//        { return lhs.name < rhs.name; }
//    };
};
int main(int argc, const char * argv[]) {
    @autoreleasepool {
        TZPerson* p = [TZPerson new];
        Method m1 = class_getInstanceMethod([p class], @selector(walk));
        struct method_t * m2 = class_getInstanceMethod([p class], @selector(run));
//        IMP imp = method_getImplementation(m2);
        method_setImplementation(m1, m2->imp);
        [p walk];
    }
    return 0;
}

OC在调用类方法时,也可以对C语言的函数进行调用,比如下面的例子

#import <Foundation/Foundation.h>
#import "TZPerson.h"
#import <objc/runtime.h>

void run() {
    NSLog(@"%s", __func__);
}

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        TZPerson* p = [TZPerson new];
        Method m1 = class_getInstanceMethod([p class], @selector(walk));
        method_setImplementation(m1, (IMP)run);
        [p walk];        
    }
    return 0;
}

OC进行调用类交换,如下

#import <Foundation/Foundation.h>
#import "TZPerson.h"
#import "TZDog.h"
#import <objc/runtime.h>

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        TZPerson* p = [TZPerson new];
        TZDog* d = [TZDog new];
        object_setClass(p, [d class]);
        [p walk];        
    }
    return 0;
}

执行结果如下:

2018-11-16 14:39:19.802920+0800 Runtime001[3662:134196] -[TZDog walk]
Program ended with exit code: 0

本来调用的Person,但是替换成了Dog类。这就是类对象发送改变。

GitHub参考
iOS进阶—目录


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

iOS进阶—Runtime基础 的相关文章

  • 减小构建尺寸

    当我在 VS2013 中使用 C 运行时库的静态链接时 有什么方法可以降低构建大小吗 我的原始文件只有 15kb 但我无法在其他计算机上运行它而不弹出缺少 dll 的消息 我决定使用静态链接 现在大小约为 100kb 我正在使用Window
  • C# - 在运行时加载 xaml 文件

    我有一个用 C 编写的 WPF 应用程序 我有一个MainWindow继承自 a 的类System Windows Window class 接下来 我的磁盘上有一个 xaml 文件 我想在运行时加载它
  • Java 原始类型值分配给泛型类型运行时 getClass() 方法错误

    public class Box
  • VC++:KB971090 并选择 Visual C 运行时 DLL 依赖项

    如您所知 Microsoft 最近为 Visual Studio 部署了安全更新 KB971090 http support microsoft com kb 971090 除此之外 这还将 Visual C 运行时 DLL 从版本 8 0
  • 尝试在java中执行命令时出错[重复]

    这个问题在这里已经有答案了 我正在尝试使用终端但从 java 运行 java 文件 意思是 我将使用 java 运行该命令 我正在尝试执行命令 cd Users apple Documents Documents workspace Use
  • Android:以编程方式更改视图的绝对位置

    如果您使用 AbsoluteLayout 我知道它已被弃用 但这是解决我的问题的唯一方法 problem https stackoverflow com questions 3438656 android scrollable horizo
  • 需要裁剪+调整大小约 300000 个文件。运行时间 = 4 天以上。如何加快 bash 脚本的速度?

    我正在努力创建视频间隔拍摄 我拍摄的所有照片都是以 4 3 宽高比拍摄的 jpg 图像 2592x1944 分辨率 我希望它们在 1920x1080 下均为 16 9 我写了一个小脚本来执行此操作 但过程不是很快 我花了大约 17 分钟来裁
  • C++ static_cast 运行时开销

    请参阅下面的代码 a 在这种情况下 简单继承 无虚拟成员 B df 中的静态转换是否有任何开销 无论如何 我发现类似问题的一些相互矛盾的答案 这就是我问的原因 b 我正在考虑制作const M1 funcA 中的 private 并引入新的
  • 在运行时从自定义 UITypeEditor 内部将自定义 TypeConverter 插入到属性上

    我创建了一个自定义 UITypeEditor 我是否可以插入一个属性 该属性也将 TypeConverter 附加到我的属性insideUITypeEditor 类 我已经尝试过以下操作 但无论我如何扭转和转动它 都没有任何反应 Attri
  • 如何在运行时更改语言而不会出现布局问题

    我有一个 winforms 应用程序 用户必须能够在运行时更改语言 为了概括该开关并避免必须对控件名称进行硬编码 我尝试了以下扩展 internal static void SetLanguage this Form form Cultur
  • 针对 Java 5 和 Java 6 的即时、内存中 Java 代码编译

    如何从 Java 5 和 Java 6 中的任意字符串 在内存中 编译 Java 代码 加载它并在其上运行特定方法 预定义 在你对此进行讨论之前 我查看了现有的实现 大多数依赖于 Java 6 编译器 API 那些不这样做的人 只能依靠技巧
  • chrome 扩展 - 我如何等待 chrome.runtime 函数?

    我在后台的操作是访问该站点并从那里获取信息 问题是代码在收到信息之前继续运行 附上显示问题的代码 背景 js chrome runtime onMessage addListener function request sender send
  • 需要特殊数组(线性场)的算法

    我有一个数组 线性场 与预先排序的数字 1 2 3 4 5 6 但这些数组向右移动 k次 now its 5 6 1 2 3 4 k 2 但我不知道k 只有数组A 现在我需要一个算法来找到 A 中的最大值 运行时间 O logn 我认为它是
  • 创建“拼写检查”,以合理的运行时间检查数据库

    我不是在询问如何实现拼写检查算法本身 我有一个包含数十万条记录的数据库 我想要做的是针对所有这些记录的表中的特定列检查用户输入 并返回具有特定汉明距离的任何匹配项 同样 这个问题不是关于确定汉明距离等 当然 目的是创建一个 您的意思是 功能
  • spring 在运行时添加数据源

    我正在开发一个带有每个租户数据库策略的 Spring Boot 多租户应用程序 要求是在运行时添加新数据库 这意味着我必须动态创建新的数据源对象 我还研究了 Spring 的 AbstractRoutingDataSource 但需要预定义
  • java中最常用的运行时异常有哪些? [关闭]

    Closed 这个问题是基于意见的 help closed questions 目前不接受答案 作为一名希望完善自己的编程技能的java程序员 我经常遇到必须创建运行时异常的情况 我知道如果明智地使用的话 这是一种很好的做法 亲自 空指针异
  • 类型稳定性如何让 Julia 如此之快?

    我听说类型稳定性使 Julia 如此之快 同时仍然与其他解释语言 例如 Python 一样具有表达能力 类型稳定性允许编译器在编译时直接根据输入类型确定函数的输出类型 因为 Julia 专门针对每种输入类型进行编译 这意味着如果所有函数都是
  • Python - 导入函数和本地声明函数之间的性能差异?

    在 Python 中导入函数与在当前文件中声明函数在性能上是否存在显着差异 我有一个小函数 单行 我经常在几个函数中使用它 py我的程序中的文件 我希望只定义一次 以便我对它所做的更改反映在各处 但是 我不确定将它用作导入函数是否会在调用它
  • 无法调试,致命信号 6 (SIGABRT) 位于 0x00007c37(代码=-6)

    我遇到了以下情况 无法调试 Android 应用程序 我可以运行它 但无法调试它 我开始了全新的项目 复制了所有内容并且它有效 意味着能够调试 但又得到了这个 我在模拟器和手机上都尝试过 但没有成功 我使用的是Android Studio
  • 在 Java Runtime.getRuntime().exec(...) 中使用引号和双引号

    我正在尝试在 Mac OSX 中从 Java 启动 Lisp 映像 使用控制台中的图像 我输入以下内容 lisp image eval package method some argument 一切都运行良好 在Java中 我在使用传递引号

随机推荐