iOS 底层:动态方法决议(unrecognized selector 处理流程)
2023-11-18 13:58:08
在前面的两篇文章中,我们探索了消息查找的流程,包括快速查找和慢速查找。在本文中,我们将开始探索消息查找未找到时候的处理流程。unrecognized selector
是我们经常遇到的一个错误,它表示消息发送找不到对应的实现方法。那么,当这种情况发生时,系统是如何处理的呢?
unrecognized selector
的产生
unrecognized selector
错误的产生,通常是因为以下几种情况:
- 类中没有实现该方法。
- 方法名写错了。
- 方法的参数类型不正确。
- 类和方法的访问权限不正确。
unrecognized selector
的处理流程
当 unrecognized selector
错误发生时,系统会执行以下步骤:
- 系统首先会检查该方法是否已经注册到运行时系统。如果该方法已经注册,那么系统会尝试调用该方法。
- 如果该方法没有注册到运行时系统,那么系统会检查该类是否实现了
- (void)forwardInvocation:(NSInvocation *)anInvocation
方法。如果该方法存在,那么系统会调用该方法。 - 如果该类没有实现
- (void)forwardInvocation:(NSInvocation *)anInvocation
方法,那么系统会检查该类是否实现了- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector
方法。如果该方法存在,那么系统会调用该方法获取方法签名。 - 如果该类没有实现
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector
方法,那么系统会向父类发送- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector
消息。 - 如果父类也没有实现
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector
方法,那么系统会一直向父类发送消息,直到找到一个实现了该方法的父类。 - 如果所有的父类都没有实现
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector
方法,那么系统会抛出unrecognized selector
错误。
forwardInvocation:
方法
- (void)forwardInvocation:(NSInvocation *)anInvocation
方法是一个特殊的实例方法,它允许我们处理 unrecognized selector
错误。当系统找不到该方法的实现时,它会调用 - (void)forwardInvocation:(NSInvocation *)anInvocation
方法,并将 anInvocation
对象作为参数传递给该方法。
anInvocation
对象包含了以下信息:
- 方法选择器
- 方法参数
- 方法返回值类型
我们可以使用 anInvocation
对象来调用其他方法,或者使用 anInvocation
对象来手动实现该方法。
methodSignatureForSelector:
方法
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector
方法是一个特殊的实例方法,它允许我们获取方法的签名。当系统找不到该方法的实现时,它会调用 - (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector
方法,并将 aSelector
作为参数传递给该方法。
aSelector
是方法选择器,它是一个指向方法名的指针。
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector
方法返回一个 NSMethodSignature
对象。NSMethodSignature
对象包含了以下信息:
- 方法返回值类型
- 方法参数类型
- 方法调用约定
总结
unrecognized selector
错误的产生,通常是因为以下几种情况:
- 类中没有实现该方法。
- 方法名写错了。
- 方法的参数类型不正确。
- 类和方法的访问权限不正确。
当 unrecognized selector
错误发生时,系统会执行以下步骤:
- 系统首先会检查该方法是否已经注册到运行时系统。如果该方法已经注册,那么系统会尝试调用该方法。
- 如果该方法没有注册到运行时系统,那么系统会检查该类是否实现了
- (void)forwardInvocation:(NSInvocation *)anInvocation
方法。如果该方法存在,那么系统会调用该方法。 - 如果该类没有实现
- (void)forwardInvocation:(NSInvocation *)anInvocation
方法,那么系统会检查该类是否实现了- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector
方法。如果该方法存在,那么系统会调用该方法获取方法签名。 - 如果该类没有实现
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector
方法,那么系统会向父类发送- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector
消息。 - 如果父类也没有实现
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector
方法,那么系统会一直向父类发送消息,直到找到一个实现了该方法的父类。 - 如果所有的父类都没有实现
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector
方法,那么系统会抛出unrecognized selector
错误。
我们可以使用 - (void)forwardInvocation:(NSInvocation *)anInvocation
方法和 - (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector
方法来处理 unrecognized selector
错误。