iOS中@selector的runtime过程

大家都知道oc是动态语言,是runtime的,怎么体现他的动态性呢,今天用SEL来分析下,之前分享过钩子其实就可以看出来了,现在具体看看OC是怎么通过SEL找到函数的。

[self performSelector:@selector(abcd)];
[self abcd];   //这种方法可能都会编译不过去

假如类方法里面我们便没有写adcd方法,这样就会奔溃了,oc是怎么做的呢

  1. 该方法调用后,OC会发出objc_msgSend,将消息传给本来查找本类中的SEL是否存在Method
  2. 假设本类不存在会查找工程里是否有分类提供了该方法
  3. 假设分类中也没有该方法,系统会将消息转发给其父类,父类收到消息后也会执行上面的操作,找方法,没找到再往上转发消息
  4. 假设最终都没有找到,就会执行最后的消息转发(message forwarding)操作
  5. 如果转发出去都没人接收的话,NSObject中的doesNotRecognizeSelector就选择抛出异常了,也就是我们看到的crash

上面的过程有点复杂,大家会觉得这样很慢,第一次的确很慢,所性objc_msgSend会将匹配结果写到映射表中缓存起来,每个类都有这样的一块缓存

整个过程就是上面将的那样,我们讲一下第4项消息转发怎么处理吧:

消息转发还分两个阶段:

1.动态方法解析:意思就是说询问接受者要不要增加个方法来实现该函数

+ (BOOL)resolveInstanceMethod:(SEL)selecotor   //对象方法
+ (BOOL)resolveClassMethod:(SEL)sel            //类方法

在方法里可以动态给类增加一个方法Method

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    
    [self performSelector:@selector(abcd)];
}

+ (BOOL)resolveInstanceMethod:(SEL)sel {
    NSString *selname = NSStringFromSelector(sel);
    if ([selname isEqualToString:@"abcd"]) {
        class_addMethod(self, sel, class_getMethodImplementation([self class], @selector(oklala)), method_getTypeEncoding(class_getInstanceMethod([self class], @selector(oklala))));
        return YES;
    }
    return [super resolveInstanceMethod:sel];
}

- (void)oklala {
    NSLog(@"oklala");
}

2.完整的消息转发:看看还有没有别的对象要处理,有转出,没有的话封装成NSInvocation对象处理

1)假如可以转给别的对象处理:

- (id)forwardingTargetForSelector:(SEL)aSelector

可以将要转发的对象返回。

@interface abcdCaller : NSObject

@end

@implementation abcdCaller

- (void)abcd {
    NSLog(@"~~~~~~");
}
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    
    [self performSelector:@selector(abcd)];
}

- (id)forwardingTargetForSelector:(SEL)aSelector {
    NSLog(@"!!!!!!!!!!!!!");
    return [[abcdCaller alloc] init];
}
@end

2)假如没有对象可以转发(完整消息转发)

- (void)forwardInvocation:(NSInvocation *)anInvocation

最后可以处理消息的机会

假设你的消息转发不处理,那么在第5步捕获异常,也是不会奔溃的

    @try {
        [self performSelector:@selector(abcd)];
    }
    @catch (NSException *exception) {
        NSLog(@"~~~~~~~~");
    }
    @finally {
        
    }
时间: 2024-10-18 00:29:34

iOS中@selector的runtime过程的相关文章

ios中View的创建过程

ios应用中控制器view的创建方式有三种:storyboard.xib和代码,当APP启动后View的具体加载过程如图(苹果官方): 假设我使用的是WYSViewController控制器 应用启动时会加载控制器的loadView, 1.如果loadView中有代码,直接用loadView中的代码来创建View 2.如果loadView中没有代码, A.当你使用了storyboard时,程序加载storyboard来创建View, B.当你使用了xib时,程序就加载xib来创建View, a.

***iOS开发中@selector的理解与应用

@selector 是什么? 1一种类型 SEL2代表你要发送的消息(方法), 跟字符串有点像, 也可以互转.: NSSelectorFromString() / NSSelectorFromString() 3可以理解为类似函数指针的东西--是能让Objective-C动态调用方法的玩意.--是 object-c 的动态后绑定技术 可以通过字符串 访问的函数指针4其实就是消息响应函数---选一个消息响应的函数地址给你的action[email protected](function_name)

ArcGIS Runtime SDK for iOS中获取ImageServiceLayer的栅格值

本文原创,转载请注明原创地址 http://blog.csdn.net/dongyu1009/article/details/37697389 用AGSImageServiceIdentifyTask可以获取ArcGISImageServiceLayer图层中的栅格值.这涉及了三个比较重要的类:AGSImageServiceIdentifyParameters.AGSImageServiceIdentifyTask和AGSImageServiceIdentifyResult,还有一个delega

iOS开发--1.对runtime的理解和整理

在我以往的面试中常常会被问到runtime,开始本人其实对runtime只是个简单的了解,用过一些常用的功能,并未仔细研究.不过看来现在iOS开发越来越关注runtime了,所有工作之余仔细查看了一些大牛的博客.本篇文章只是对一些大牛博客的整理,还有一些自己对runtime的不成熟的理解,只是为了方便学习.希望大家多多指点批评 附带上大牛博客:onevcat的博客:runtime的博客 一:基本概念 Runtime简称运行时,基本是用汇编和C语言编写的,只是苹果为了动态系统的高效而作出的努力.点

iOS 中的 HotFix 方案总结详解

相信HotFix大家应该都很熟悉了,今天主要对于最近调研的一些方案做一些总结.iOS中的HotFix方案大致可以分为四种: WaxPatch(Alibaba) Dynamic Framework(Apple) React Native(Facebook) JSPatch(Tencent) WaxPatch WaxPatch是一个通过Lua语言编写的iOS框架,不仅允许用户使用 Lua 调用 iOS SDK和应用程序内部的 API, 而且使用了 OC runtime 特性调用替换应用程序内部由 O

ios学习路线—Objective-C(Runtime消息机制)

RunTime简称运行时.就是系统在运行的时候的一些机制,其中最主要的是消息机制.对于C语言,函数的调用在编译的时候会决定调用哪个函数( C语言的函数调用请看这里 ).编译完成之后直接顺序执行,无任何二义性.OC的函数调用成为消息发送.属于动态调用过程.在编译的时候并不能决定真正调用哪个函数(事实证明,在编 译阶段,OC可以调用任何函数,即使这个函数并未实现,只要申明过就不会报错.而C语言在编译阶段就会报错).只有在真正运行的时候才会根据函数的名称找到对应的函数来调用. 那OC是怎么实现动态调用

iOS开发笔记之Runtime实用总结

前言 runtime的资料网上有很多了,部分有些晦涩难懂,我通过自己的学习方法总结一遍,主要讲一些常用的方法功能,以实用为主,我觉得用到印象才是最深刻的.另外runtime的知识还有很多,想要了解更多可以一些翻译的官方文档(有点枯燥) 什么是runtime? runtime 是 OC底层的一套C语言的API(引入 <objc/runtime.h> 或<objc/message.h>),编译器最终都会将OC代码转化为运行时代码,通过终端命令编译.m 文件:clang -rewrite

iOS开发——高级特性&amp;Runtime运行时特性详解

Runtime运行时特性详解 本文详细整理了 Cocoa 的 Runtime 系统的知识,它使得 Objective-C 如虎添翼,具备了灵活的动态特性,使这门古老的语言焕发生机.主要内容如下: 引言 简介 与Runtime交互 Runtime术语 消息 动态方法解析 消息转发 健壮的实例变量(Non Fragile ivars) Objective-C Associated Objects Method Swizzling 总结 引言 曾经觉得Objc特别方便上手,面对着 Cocoa 中大量

ios中的几种多线程实现

iOS 支持多个层次的多线程编程,层次越高的抽象程度越高,使用起来也越方便,也是苹果最推荐使用的方法.下面根据抽象层次从低到高依次列出iOS所支持的多线程编程范式:1, Thread;2, Cocoa operations;3, Grand Central Dispatch (GCD) (iOS4 才开始支持)下面简要说明这三种不同范式:Thread 是这三种范式里面相对轻量级的,但也是使用起来最负责的,你需要自己管理thread的生命周期,线程之间的同步.线程共享同一应用程序的部分内存空间,它