MJExtension代码解释
Runtime 是什么?
objective-C会把函数调用的转换为消息发送,objc_MsgSend(receiver, msg), 注意,recevier指的是消息的接受者。那么self, super的区别是什么?其实 super 是一个 Magic Keyword, 它本质是一个编译器标示符,和 self 是指向的同一个消息接受者!他们两个的不同点在于:super 会告诉编译器,调用 class 这个方法时,要去父类的方法,而不是本类里的。不管调用[self class]还是[super class],接受消息的对象都是当前 self指向的实例。在代码中使用self可以获取recevier,使用_cmd获取method。
1.SEL 的含义:
在前面我们看到方法选标 SEL 的定义为:
它是一个指向 objc_selector 指针,表示方法的名字/签名。
typedef struct objc_selector *SEL;
2. IMP 的含义:
在前面我们也看到 IMP 的定义为:
typedef id (*IMP)(id, SEL, ...);
根据前面id 的定义,我们知道 id是一个指向 objc_object 结构体的指针,该结构体只有一个成员isa,所以任何继承自 NSObject 的类对象都可以用id 来指代,因为 NSObject 的第一个成员实例就是isa。
至此,我们就很清楚地知道 IMP 的含义:IMP 是一个函数指针,这个被指向的函数包含一个接收消息的对象id(self 指针), 调用方法的选标 SEL (方法名),以及不定个数的方法参数,并返回一个id。也就是说 IMP 是消息最终调用的执行代码,是方法真正的实现代码 。我们可以像在C语言里面一样使用这个函数指针
3. Method是,包含了方法名称,与实现的结构。
typedef struct objc_method *Method;
typedef struct objc_ method {
SEL method_name;
char *method_types;
IMP method_imp;
};
消息的转发
给一个对象调用它不存在的方法,会发生什么?
It works like this: When an object can’t respond to a message because it doesn’t have a method matching the selector in the message, the runtime system informs the object by sending it a
forwardInvocation:message. Every object inherits aforwardInvocation:method from theNSObjectclass. However,NSObject’s version of the method simply invokesdoesNotRecognizeSelector:. By overridingNSObject’s version and implementing your own, you can take advantage of the opportunity that theforwardInvocation:message provides to forward messages to other objects
会发生,forwardingInvocation:message, NSObject实现是doesNotRecongizeSelectoer:,所以我们可以重写这个实现。通过消息转发,调用其他类的实现,起到了多重继承的效果
- (void)forwardInvocation:(NSInvocation *)anInvocation
{
if ([someOtherObject respondsToSelector:
[anInvocation selector]])
[anInvocation invokeWithTarget:someOtherObject];
else
[super forwardInvocation:anInvocation];
}
替代的对象,如果一个类很大,很复杂,你想懒加载,可以先使用一个替代类进行占位,等到你需要的时候再消息转发。
If you want your objects to act as if they truly inherited the behavior of the objects they forward messages to, you’ll need to re-implement the
respondsToSelector:andisKindOfClass:methods to include your forwarding algorithm:
如果再消息转发的情况下,支持某些方法,如何感知,需要重写自己版本的几个函数
- (BOOL)respondsToSelector:(SEL)aSelector
{
if ( [super respondsToSelector:aSelector] )
return YES;
else {
/* Here, test whether the aSelector message can *
* be forwarded to another object and whether that *
* object can respond to it. Return YES if it can. */
}
return NO;
}
如果一直找到根类都没有找到对应的方法,object_msgForward就作为替代IMP,并执行
objc_msgForward消息转发做的几件事:
调用resolveInstanceMethod:方法 (或resolveClassMethod:)。允许用户在此时为该 Class 动态添加实现。如果有实现了,则调用并返回YES,那么重新开始objc_msgSend流程。这一次对象会响应这个选择器,一般是因为它已经调用过class_addMethod。如果仍没实现,继续下面的动作。
调用forwardingTargetForSelector:方法,尝试找到一个能响应该消息的对象。如果获取到,则直接把消息转发给它,返回非 nil 对象。否则返回 nil ,继续下面的动作。注意,这里不要返回 self ,否则会形成死循环。
This method gives an object a chance to redirect an unknown message sent to it before the much more expensive
forwardInvocation:machinery takes over. This is useful when you simply want to redirect messages to another object and can be an order of magnitude faster than regular forwarding. It is not useful where the goal of the forwarding is to capture the NSInvocation, or manipulate the arguments or return value during the forwarding.
调用methodSignatureForSelector:方法,尝试获得一个方法签名。如果获取不到,则直接调用doesNotRecognizeSelector抛出异常。如果能获取,则返回非nil:创建一个 NSlnvocation 并传给forwardInvocation:。
This method is used in the implementation of protocols. This method is also used in situations where an
NSInvocationobject must be created, such as during message forwarding. If your object maintains a delegate or is capable of handling messages that it does not directly implement, you should override this method to return an appropriate method signature.
调用forwardInvocation:方法,将第3步获取到的方法签名包装成 Invocation 传入,如何处理就在这里面了,并返回非ni。
调用doesNotRecognizeSelector:,默认的实现是抛出异常。如果第3步没能获得一个方法签名,执行该步骤。
Important
To respond to methods that your object does not itself recognize, you must override
methodSignatureForSelector:in addition toforwardInvocation:. The mechanism for forwarding messages uses information obtained frommethodSignatureForSelector:to create theNSInvocationobject to be forwarded. Your overriding method must provide an appropriate method signature for the given selector, either by pre formulating one or by asking another object for one.
To assist the runtime system, the compiler encodes the return and argument types for each method in a character string and associates the string with the method selector. The coding scheme it uses is also useful in other contexts and so is made publicly available with the
@encode()compiler directive
Objects are treated like structures. For example, passing the NSObject class name to @encode() yields this encoding:, NSObject就只有一个isa指针
{NSObject=#}
之前用MJExtension在多线程下一直崩溃,后来MJExtension修复了,就是加了一个同步, https://github.com/CoderMJLee/MJExtension/issues/518
+ (instancetype)cachedTypeWithCode:(NSString *)code
{
MJExtensionAssertParamNotNil2(code, nil);
@synchronized (self) {
MJPropertyType *type = types_[code];
if (type == nil) {
type = [[self alloc] init];
type.code = code;
types_[code] = type;
}
return type;
}
}
MJExtension代码解释的更多相关文章
- Deep Learning入门视频(下)之关于《感受神经网络》两节中的代码解释
代码1如下: #深度学习入门课程之感受神经网络(上)代码解释: import numpy as np import matplotlib.pyplot as plt #matplotlib是一个库,p ...
- [ARM] Cortex-M Startup.s启动文件相关代码解释
1. 定义一个段名为CSTACK, 这里: NOROOT表示如何定义的段没有被关联,那么同意会被优化掉,如果不想被优化掉就使用ROOT. 后面的括号里数字表示如下: (1):这个段是2的1次方即2字节 ...
- word2vec代码解释
以前看的国外的一篇文章,用代码解释word2vec训练过程,觉得写的不错,转过来了 原文链接 http://nbviewer.jupyter.org/github/dolaameng/tutorial ...
- javascript代码解释执行过程
javascript是由浏览器解释执行的脚本语言,不同于java c,需要先编译后运行,javascript 由浏览器js解释器进行解释执行,总的过程分为两大块,预编译期和执行期 下面的几个demo解 ...
- 临时2级页表的初始化过程 head_32.S 相关代码解释
page_pde_offset = (__PAGE_OFFSET >> 20); /* __PAGE_OFFSET是0xc0000000,page_pde_offset = 3072 = ...
- 零基础学python之入门和列表数据(附详细的代码解释和执行结果截图)
Python学习笔记 1 快速入门 下载安装好Python之后,在开始找到 双击打开一个窗口,这是一个shell界面编辑窗口,点击左上角的file——new file新建一个窗口,这里可以输入完整的代 ...
- java 的一个hellow word 代码解释
/* This is a simple Java program. Call this file "Example.java". */(上面是注释的方法) class Exampl ...
- TensorFlow的序列模型代码解释(RNN、LSTM)---笔记(16)
1.学习单步的RNN:RNNCell.BasicRNNCell.BasicLSTMCell.LSTMCell.GRUCell (1)RNNCell 如果要学习TensorFlow中的RNN,第一站应该 ...
- 参数传递方法(用Delphi的汇编代码解释)
参数传递方法 李纬的InsideVCL<第一章>中提到Windows定义的回调函数 typedef LRESULT (CALLBACK*WNDPROC)(HWND,UNIT,WPARAM, ...
随机推荐
- 移动APP项目总结
刚开始做这个项目,看着觉得内容不多,但细节问题很多,很多容易出错的地方, 如下: 项目效果 起初是这样做的 HTML: <div class="seller"> < ...
- uni-app,wex5,APPcan,ApiCloud几款国内webapp开发框架的选型对比
框架列表. https://www.cnblogs.com/xiaxiaxia/articles/5705557.html 前言 近期,要开一个新的项目,APP类型.最重要的需求就是能够随时调整APP ...
- select2 javascript控件 如何设置指定的值
$("#id").select2("data") 这样的方法无效 要使用$("#selectNull").val("") ...
- <target>.ID 和 <source>.ID 的属性冲突: DataType 属性不匹配
ORACLE数据库主键的数据类型为number ,如果不指定长度会有 Merge报 <target>.ID 和 <source>.ID 的属性冲突: DataType 属性不匹 ...
- HTTP Error 400. The request hostname is invalid
HTTP Error 400. The request hostname is invalid 错误, 检查服务的iis服务得知,是因为在绑定主机和端口的那一步时也指定了相应的域名. 解决办法: 去掉 ...
- 如何打jar包 学习笔记
jar包是由.class文件压缩而成.要查看jar包中的内容,使用压缩工具 解压缩即可.也可以做修改,并重新打成jar包.总结一下最近学到的一些打jar包的方法: 一.DOS下使用jar命令 打jar ...
- .NET Core HttpClient调用腾讯云对象存储Web API的"ERROR_CGI_PARAM_NO_SUCH_OP"问题
开门见山地说一下问题的原因:调用 web api 时请求头中多了双引号,请求体中少了双引号. 腾讯云提供的对象存储(COS)C# SDK 是基于 .NET Framework 用 WebRequest ...
- GMM-实现聚类的代码示例
Matlab 代码: % GMM code function varargout = gmm(X, K_or_centroids) % input X:N-by-D data matrix % inp ...
- display style edit
https://html.spec.whatwg.org/multipage/interaction.html#attr-contenteditable <!doctype html> & ...
- Flash builder 、flash cs6、 as 3.0研究
1.Flash/Actionscript3 载入资源文件方法考 http://zengrong.net/post/1107.htm 2.使用Flash Professional CS5和Flash B ...