美文网首页
所谓的消息

所谓的消息

作者: 奇异果好补 | 来源:发表于2018-04-24 00:30 被阅读11次

消息

在C++或Java里,类与类的行为方法之间的关系非常紧密,一个方法必定属于一个类,且于编译时就已经绑定在一起,所以你不可能调用一个类里没有的方法。而在Objective-C中就比较简单了,类和消息之间是松耦合的,方法调用只是向某个类发送一个消息,该类可以在运行时再确定怎么处理接受到的消息。也就是说,一个类不保证一定会响应接收到的消息,如果收到了一个无法处理的消息,那么程序就是简单报一个错而已。

Objective-C 是 C 语言的超集,所有的方法在底层都是简单朴素的 C 方法,运行时决定了当传入一个消息时具体哪个方法被调用。

像对象发送一个消息的代码类似于这个:

id returnValue = [someObject messageName:parameter];

最终这个代码会变成类似下面这个C方法:

id returnValue = objc_msgSend(someObject, @selector(messageName:), parameter);

消息传递

当一个对象接受到它不能理解的消息时,消息传递机制会被启用。

在消息真正“不被处理”之前,有三次可以处理它的机会。

第一次是动态方法解析

当一个对象接受到它不能理解的消息时,第一个被调用的方法是一个类方法:

+ (BOOL)resolveInstanceMethod:(SEL)selector;

这个方法以传入对象的 selector 作为参数,返回一个布尔值,这个值指示了有没有一个实例方法被添加到类中,使得类现在可以处理这个 selector。

如果失败,使用替代接收者

第二次尝试是询问接受这个消息的类,有没有一个替代接受者可以处理这个未知消息,对应的函数是:

- (id)forwardingTargetForSelector:(SEL)selector;

未知 selector 被传入,如果有替代者,那么替代者对象会被返回,否则返回nil

最后,使用消息传递机制

如果上面这些尝试都失败了,只能使用完成的消息传递机制。首先创建一个NSInvocation对象来包装好这个没有处理的消息的所有细节。

用于传递消息的方法是:

- (void)forwardInvocation:(NSInvocation *)invocation;

这个方法的实现应该总是调用其父类的实现。最终NSObject的实现会唤醒doesNotRecognizeSelector来触发一个“未处理的 selector” 异常。

Method Swizzling

当消息传入一个函数时,实际调用的方法是在运行时决定的。这就允许我们改变某个消息传入时实际调用的方法。通常这种办法用于改变那些看不到源码的类的功能。

类的方法列表包含了一系列的 selector 名字和对应的实现之间的映射,用于指导动态消息系统去哪里找某个消息对应的实现。这些对应的实现存储为一种叫做IMP的函数指针,其原型如下:

id (*IMP)(id, SEL, ...)

要想得到某个 selector 对应的实现,可以使用下面的函数:

Method class_getInstanceMethod(Class aClass, SEL aSelector)

想添加一个实现,可以使用下面的函数:

BOOL class_addMethod(Class class, SEL originalSelector, Method m1, const char* encoding)

要想交换两个实现,可以使用:

void method_exchangeImplementations(Method m1, Method m2)

Swizzling 通常被认为是一种黑科技,它容易导致不可预测的行为和难以预知的结果。尽管它不是十分安全,但是只要能做到下面几点,使用它相对而言还是比较安全的:

  • 总是调用方法本来的实现(除非你真的不需要这么做)
  • 避免冲突
  • 明白你在干什么
  • 小心谨慎

参考资料

相关文章

  • 所谓的消息

    消息 在C++或Java里,类与类的行为方法之间的关系非常紧密,一个方法必定属于一个类,且于编译时就已经绑定在一起...

  • 所谓的消息,是干嘛用的?

    故事#股票大作手回忆录#摩尔看到棉花市场有行情,吃进14万包棉花市场多头仓位,但因为仓位太大,无法找到买盘出手。这...

  • 消息队列之异步消息基本概念以及ActiveMQ整合Spring常

    一 简介 (1)异步消息: 所谓异步消息,跟RMI远程调用、webservice调用是类似的,异步消息也是用于应用...

  • Spring Cloud Stream 进阶配置——使用延迟队列

    ps: 本文所有代码可在 这里 查看。 延迟队列 延迟队列 操作的对象是延迟消息,所谓 “延迟消息” 是指当消息被...

  • 延迟队列

    概念     延迟队列存储的对象是对应的延迟消息,所谓"延迟消息"是指当消息被发送以后,并不想让消费者立刻拿到消息...

  • SpringBoot对异步消息(MQ)的支持

    1.异步消息的定义   异步消息的主要目的是为了系统与系统之间的通信,所谓异步消息即消息发送者无需等待消息接收者的...

  • spring boot 集成rabbitmq 实现延迟队列

    rabbitmq 实现延迟队列 什么是延迟队列 延迟队列存储的对象肯定是对应的延时消息,所谓”延时消息”是指当消息...

  • 10.延迟队列

    文章参考:Rabbit实战指南 延迟队列 延迟队列存储的对象是对应的延迟消息,所谓“延迟消息”是指当消息被发送以后...

  • 2023-01-26

    感觉无所谓了一个回复消息的机器

  • RabbitMQ实现延迟消费(延迟队列)

    什么是延迟队列延迟队列存储的对象是对应的延时消息,所谓”延时消息”是指当消息被发送以后,并不想让消费者立即拿到消息...

网友评论

      本文标题:所谓的消息

      本文链接:https://www.haomeiwen.com/subject/cofdlftx.html