swizzle method 和消息转发机制的实际使用

我的工程结构,如图 1-0

        图  1-0

在看具体实现以前,先捋以下 实现思路。

ViewController 中有一个-(void)Amethod;A方法。

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

1.swizzle method

在ViewController 的 -(void)viewDidLoad中调用 Amentohd;运行输出

                                         图 1-1

创建一个ViewController 的Category,重写+(void)Load;方法(因为这个方法只会在类被加载时,调用一次。至于initialize,它们之间区别,参考 iOS - + initialize 与 +load),在实现-(void)Bmethod;

+(void)load{
     Class class = [self class];
    Method m3 =class_getInstanceMethod(class, @selector(Amethod));
    Method m4  =class_getInstanceMethod(class, @selector(Bmethod));
    method_exchangeImplementations(m3, m4);

}

-(void)Bmethod{

NSLog(@"swizzle method succuess :Bmenthod");

}

运行结果如下图1-2,

                        1-2

这就是一个简单的交换方法的思路,如果你认真的看了上面的 参考文章,就会发现+(void)Load;是在所有类加载的时候执行的, 那么如果在这个方法里,执行过多操作,是会推延APP启动时间的。所以不要在里面做过多的操作。

由于swizzle method is not atomic,不是线程安全的,所以你可以在dispatce_once 中完成swizzle。

+(void)load{
            Class class = [self class];
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        Method m3 =class_getInstanceMethod(class, @selector(Amethod));
        Method m4  =class_getInstanceMethod(class, @selector(Bmethod));/*下面代码的主要思路就是 主类有没有实现Amethod, 实现了,就交换Amenthod和Bmenthod,没实现就给她加上Amethod,但IMP和enconding type是Bmethod的。 在加上Bmenthod,但IMP 和 encoding type是Amethod的。*/ 
        BOOL success = class_addMethod(class, method_getName(m3), method_getImplementation(m4), method_getTypeEncoding(m4));
        if (success) {
            class_replaceMethod(class, method_getName(m4), method_getImplementation(m3), method_getTypeEncoding(m3));
        }else{
        method_exchangeImplementations(m3, m4);
        }
    });
}

以上,就是 简单的swizzle method。你也可以在Bmethod 中再次调用Bmethod。不会出现递归。动动脑子就知道了。

2.消息转发 : 有三种方法是去补救实现相应方法。也可以做多继承使用。

我们在ViewController 中声明一个 button ,但是不实现它的绑定方法

    UIButton *pushA = [[UIButton alloc]initWithFrame:CGRectMake(200, 200, 50, 50)];
    [pushA setTitle:@"pusha" forState:(UIControlStateNormal)];
    [pushA addTarget:self action:@selector(pushA:) forControlEvents:(UIControlEventTouchUpInside)];
    [self.view addSubview:pushA];

在它的分类中,实现下面代码,当一个实例方法没有实现就会调用 +(BOOL)resolveInstanceMethod:(SEL)sel;相对应对还有类方法+(BOOL)resolveClassMethod:(SEL)sel;

+(BOOL)resolveInstanceMethod:(SEL)sel{
    NSString *selectionString = NSStringFromSelector(sel);
    if ([selectionString isEqualToString:@"pushA:"]) {
        class_addMethod(self, sel, (IMP)pushA, "[email protected]:*");// 在我之前关于YYModel的文中提到 Encoding type
    }
    return [super resolveInstanceMethod:sel];// 这里无论返回yes 还是NO ,如果方法没有实现都会调用第二种补救方式
}//函数的具体实现 也是IMP
void pushA(id self,SEL sel,UIButton *sender){
    NSLog(@"动态添加方法%@",self);
    AViewController *vc = [AViewController new];
    AViewController *sourceVC = self;
    [sourceVC.navigationController pushViewController:vc animated:YES];

}

上面是第一种 补救方法。第二种就是-(id)forwardingTargetForSelector:(SEL)aSelector;

在ViewController 中在[self performSelector:@selector(Cmethod)];但不在Viewcontroller 中实现Cmenthod(关于 -(void)performSelector 还有很多方法,也会稍后添加)

在分类中,添加转发方法,

-(id)forwardingTargetForSelector:(SEL)aSelector{
    AViewController * avc = [AViewController new];
    if ([avc respondsToSelector:aSelector]) {
         return avc;
    }
    return [super forwardingTargetForSelector:aSelector];
}

在AViewController实现 -(void)Cmenthod;就完成消息转发给另一个对象。

第三种补救方式是- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector;配合- (void)forwardInvocation:(NSInvocation *)anInvocation

使用,其中还要介绍NSInvocation 对象。还有 - (void)doesNotRecognizeSelector:(SEL)aSelector; 所以今天先到这,以后会补充

时间: 2024-10-12 02:14:51

swizzle method 和消息转发机制的实际使用的相关文章

消息转发机制入门篇

一.何时处发消息转发机制? 解:当对象接收到无法解读的消息后,就会启动“消息转发”(message forwarding)机制,程序员可经由此过程告诉对象应该如何处理未知消息. 如:-[__NSCFNumber lowercaseString] :unrecognized selector sent to instance 0x87 上面这段异常信息是由NSObjc 的”doesNotRecognizeSelector”方法所抛出的,此异常表明:消息接收者的类型是_ _NSCFNumber,而该

《Effective Objective-C 2.0》—(第11-14条)—运行时动态绑定、objc_msgSend、消息转发机制

第11条:理解objc_msgSend的作用 在对象上调用方法是OC中经常使用的功能.用OC术语来说这叫做:"传递消息"(pass a message).消息有"名称"(name)或者"选择子"(selector),可以接收参数,而且可能还有返回值. 由于OC是C的超集,所以最好理解C语言的函数调用方式.C语言使用"静态绑定",就是说在编译期就能决定运行时所应调用的函数.以下列代码为例: #import <stdio.h

理解消息转发机制

消息转发分为两大阶段.第一阶段先征询接收者,所属的类,看其是否能动态添加方法,以处理当前这个"未知的选择子"(unknown selector),这叫做"动态方法解析"(dynamic method resolution).第二阶段涉及"完整的消息转发机制".如果运行期系统已经把第一阶段执行完了,那么接收者自己就无法再以动态新增方法的手段来响应包含该选择子的消息了.此时,运行期系统会请求接收者以其他手段来处理与消息相关的方法调用.这又细分为两小步

iOS runtime探究(二): 从runtime開始深入理解OC消息转发机制

你要知道的runtime都在这里 转载请注明出处 http://blog.csdn.net/u014205968/article/details/67639289 本文主要解说runtime相关知识,从原理到实践.由于包括内容过多分为下面五篇文章详细解说.可自行选择须要了解的方向: 从runtime開始: 理解面向对象的类到面向过程的结构体 从runtime開始: 深入理解OC消息转发机制 从runtime開始: 理解OC的属性property 从runtime開始: 实践Category加入属

Effective Objective-C 2.0 — 第12条:理解消息转发机制

11 条讲解了对象的消息传递机制 12条讲解对象在收到无法解读的消息之后会发生什么,就会启动“消息转发”(message forwarding)机制, 若对象无法响应某个选择子,则进入消息转发流程. 1,通过运行期的动态方法解析功能,可以在需要用到某个方法时再将其加入类中. 2,对象可以把其无法解读的某些选择子转交给其他对象来处理. 经过上述两步之后,如果还是没办法处理选择子,那就启动完整的消息转发机制. 动态方法解析 对象在收到无法解读的消息之后,首先调用其所属类的下列类方法 + (BOOL)

第12条:理解消息转发机制

要点 若对象无法响应某个选择子,则进入消息转发流程. 通过运行期的动态方法解析功能,我们可以在需要用到某个方法时再将其加入类中. 对象可以把其无法解读的某些选择子转交给其他对象来处理. 经过上述两步之后,如果还是没办法处理选择子,那就启动完整的消息转发机制.

iOS消息转发机制

iOS消息转发机制 “消息派发系统”(message-dispatch system) 若想令类能够理解某条消息,我们必须实现出对应的方法才行.但是,在编译器向类发送其无法解读的消息时并不会报错,因为在运行期可以继续向类中添加方法,所以编译器在编译时还无法确定类中到底会不会有某个方法的实现.当对象接收到无法解读的消息时,就会启动“消息转发”机制,我们可以经由此过程告诉对象应该如何处理未知消息. 消息转发分为两个阶段.第一阶段先征询接收者所属的类,看其是否能动态添加方法,已处理当前这个“未知的选择

关于OC中消息转发机制的理解以及在项目中的实际应用

<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">关于OC中的消息转发机制想必大家都很了解,现在来温习一下:</span> 一.什么是消息转发? @selector 是什么? 1一种类型 SEL 2代表你要发送的消息(方法), 跟字符串有点像, 也可以互转.: NSSelectorFromString()   /   NSS

runtime消息转发机制

Objective-C 扩展了 C 语言,并加入了面向对象特性和 Smalltalk 式的消息传递机制.而这个扩展的核心是一个用 C 和 编译语言 写的 Runtime 库.它是 Objective-C 面向对象和动态机制的基石. Objective-C 是一个动态语言,这意味着它不仅需要一个编译器,也需要一个运行时系统来动态得创建类和对象.进行消息传递和转发.理解 Objective-C 的 Runtime 机制可以帮我们更好的了解这个语言,适当的时候还能对语言进行扩展,从系统层面解决项目中的