Message Forwarding + 动态绑定

2024-03-25 04:08

本文主要是介绍Message Forwarding + 动态绑定,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

> “unrecognized selector sent to instance …" 错误
动态绑定:objc_msgSend的实现,查找implementation表,最终是C函数形式的调用。

当某个类(以及继承树上的父类)编译时没有动态实现被调用的method的时候,一般情况下会被NSObject处理这个method(selector)并抛出异常。

我们有两种常用(三种)方法来动态的补充使得相应的lei可以处理此selector。

一种是动态方法手段(Dynamic Method Resolution),第二种是委托其他对象处理(Replacement Receiver)。下边通过例子直接说明。

=============================================
NormalObject.h
@interface NormalObject : NSObject
- (
void )showMe;
// 实际上没有显式实现这个 selector
- (
void )testMe;
@end

==============================================
#import "NormalObject.h"
#import
"ReplacementObject.h"
#import
<objc/runtime.h>

#define kUseDynamicMethod YES

@interface NormalObject ()
@property ( strong , nonatomic ) ReplacementObject *replacement;
@end

@implementation NormalObject

- (
instancetype )init
{
   
self = [ super init ];
   
if ( self ) {
       
self . replacement = [[ ReplacementObject alloc ] init ];
    }
   
return self ;
}

#pragma mark - Dynamic Method Resolution
// 当且仅当未显示实现的 selector 被调用时,这里会被调用。- 再次调用同样的selector,这里不会被执行,因为已经cached了
+ ( BOOL )resolveInstanceMethod:( SEL )sel{
   
if ( kUseDynamicMethod ) {
       
NSString *selName = NSStringFromSelector (sel);
        NSLog(@"required for: %@", selName);
// 使用 class_addMethod 动态加入method,此后每次对testMe的调用都会直接调用 impAddedMethod
        class_addMethod ( self , sel, ( IMP ) impAddedMethod , "v@:" );
       
return YES ;
    }
else {
       
return NO ;
    }
}

// must be a C method
void impAddedMethod( id self , SEL _sel){
   
NSLog ( @"You guy send an unknown selector!!!" );
}

#pragma mark - Replacement Receiver
- ( id )forwardingTargetForSelector:( SEL )aSelector{
   
NSLog ( @"%s called" , __FUNCTION__ );
   
return self . replacement ;
}

- (
void )showMe{
   
NSLog ( @"NormalObject showMe called" );
}
@end
==============================================
辅助类:
@interface ReplacementObject : NSObject
- (
void )testMe;
@end

@implementation ReplacementObject
- (
void )testMe{
   
NSLog ( @"[ReplacementObject] Wahahahah, i implement this!" );
}
@end
==============================================
调用

    [obj1 showMe ]; // 一般情况
    [obj1 testMe ]; // testMe没用命中,通过 resolveInstanceMethod forwardingTargetForSelector寻找解决方案,没有找到的话由NSObject来抛异常
    NSLog ( @"call it again" );
    [obj1 testMe]; //  第二次调用, resolveInstanceMethod不会再次触发,因为已经cached了。 forwardingTargetForSelector则会每次都执行,因此Dynamic Method的效率会更高。

两者使用场景不同。 Dynamic Method适用于@dynamic修饰的property的setter和getter的实现。Replacement Receiver适用于用composition模式来达到多重继承的效果。

这篇关于Message Forwarding + 动态绑定的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/843804

相关文章

vue+elementui--$message提示框被dialog遮罩层挡住问题解决

最近碰到一个先执行this.$message提示内容,然后接着弹出dialog带遮罩层弹框。那么问题来了,message提示框会默认被dialog遮罩层挡住,现在就是要解决这个问题。 由于都是弹框,问题肯定是出在z-index比重问题。由于用$message方式是写在js中而不是写在html中所以不是很好直接去改样式。 不过好在message组件中提供了customClass 属性,我们可以利用

【杂记-浅谈DHCP动态主机配置协议】

DHCP动态主机配置协议 一、DHCP概述1、定义2、作用3、报文类型 二、DHCP的工作原理三、DHCP服务器的配置和管理 一、DHCP概述 1、定义 DHCP,Dynamic Host Configuration Protocol,动态主机配置协议,是一种网络协议,主要用于在IP网络中自动分配和管理IP地址以及其他网络配置参数。 2、作用 DHCP允许计算机和其他设备通

JavaWeb系列六: 动态WEB开发核心(Servlet) 上

韩老师学生 官网文档为什么会出现Servlet什么是ServletServlet在JavaWeb项目位置Servlet基本使用Servlet开发方式说明快速入门- 手动开发 servlet浏览器请求Servlet UML分析Servlet生命周期GET和POST请求分发处理通过继承HttpServlet开发ServletIDEA配置ServletServlet注意事项和细节 Servlet注

OSG学习:LOD、数据分页、动态调度

LOD(level of detail):是指根据物体模型的结点在显示环境中所处的位置和重要度,决定物体渲染的资源分配,降低非重要物体的面数和细节度,从而获得高效率的渲染运算。在OSG的场景结点组织结构中,专门提供了场景结点osg::LOD来表达不同的细节层次模型。其中,osg::LOD结点作为父节点,每个子节点作为一个细节层次,设置不同的视域,在不同的视域下显示相应的子节点。 数据分页:在城市

Java代理-动态字节码生成代理的5种方式

上篇讲到了代理模式出现的原因,实现方式以及跟其他相似设计模式的区别。传送门@_@ http://blog.csdn.net/wonking666/article/details/79497547 1.静态代理的不足 设计模式里面的代理模式,代理类是需要手动去写的。但是手写代理的问题颇多 1.如果不同类型的目标对象需要执行同样一套代理的逻辑,比如说在方法调用前后打印参数和结果,那么仍然需要为每

Android插件化学习之路(一)之动态加载综述

前段时间,公司项目完成了插件化的开发,自己也因此学习了很多Android插件化的知识,于是想把这些内容记录下来,本次带来Android插件化的第一篇:动态加载综述 Android插件化学习之路(一)之动态加载综述 Android插件化学习之路(二)之ClassLoader完全解析 Android插件化学习之路(三)之调用外部.dex文件中的代码 Android插件化学习之路(四)之使用插件中的R

在WinCE的C#编程中,需要静态调用C++的动态库,需要添加using System.Runtime.InteropServices

using System.Runtime.InteropServices;         [DllImport("Win32DLL.dll", EntryPoint = "WriteREG_SZToRegTCHAR")]         private static extern bool WriteREG_SZToRegTCHAR(int iFlag, string regKeyP

C#界面动态布局 界面控件随着界面大小尺寸变化而变化

要想写一个漂亮的界面,光靠利用Anchor和Dock属性是远远不够的,我们需要用到相对布局,就是不管窗口大小怎么变化,控件相对父控件的相对位置保持不变。可惜c#里没有提供按照百分比布局。所以只能自己再resize()事件里调整控件位置。 首先在窗体的构造函数里保存父窗体的长宽,以及每个控件的X,Y坐标的相对位置:  int count = this.Controls.Count * 2 + 2;

VUE2 elementui 动态表单嵌套新增移除

VUE2 elementui 动态表单嵌套新增移除 代码 <template><div><el-button type="text" @click="dialogTableVisible = true">打开嵌套表格的 Dialog</el-button><el-dialog title="收货地址" :visible.sync="dialogTableVisible"><el-form r

动态规划DP--斐波那契数、爬楼梯、使用最小花费爬楼梯等示例代码

动态规划DP 文章目录 动态规划DP509. 斐波那契数70. 爬楼梯746. 使用最小花费爬楼梯62. 不同路径63. 不同路径II343.整数拆分 509. 斐波那契数 509. 斐波那契数 斐波那契数 (通常用 F(n) 表示)形成的序列称为 斐波那契数列 。该数列由 0 和 1 开始,后面的每一项数字都是前面两项数字的和。也就是: F(0) = 0,F(1) =