在obj-c中我们可以向一个实例发送消息,相当于c/c++ java中的方法调用,只不过在这儿是说发送消息,实例收到消息后会进行一些处理。比如我们想调用一个方法,便向这个实例发送一个消息,实例收到消息后,如果能respondsToSelector,那么就会调用相应的方法。如果不能respond一般情况下会crash。如果不想要crash,那么就要进行相应的方法处理,或者进行节点重定向转发。
obj-c 向一个实例发送一个消息后,系统是处理的流程:
1. 发送消息如:[self function]
2. 系统会check是否能response这个消息
系统是如何check实例是否能response消息呢?如果实例本身就有相应的response,那么就会进行响应,如果没有,系统就会发出methodSignatureForSelector消息,寻问它这个消息是否有效?有效就返回对应的方法地址之类的,无效则返回nil。如果是nil就会crash, 如果不是nil接着发送forwardInvocation消息。
3. 如果能response则调用相应方法,不能则抛出异常
demo验证此过程
crash 错误
代码例子:
viewController
TestModel * model = [[TestModel alloc]init];
[model testMethod];
TestModel.h
-(void)testMethod;
TestModel.m
-(NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector
{
if (aSelector == @selector(testMethod))
{
return [NSMethodSignature signatureWithObjCTypes:"v@:"];
}
return nil;
}
-(void)forwardInvocation:(NSInvocation *)anInvocation
{
if (anInvocation.selector == @selector(testMethod))
{
TestModelHelper1 *h1 = [[TestModelHelper1 alloc] init];
TestModelHelper2 *h2 = [[TestModelHelper2 alloc] init];
[anInvocation invokeWithTarget:h1];
[anInvocation invokeWithTarget:h2];
}
}
@implementation TestModelHelper1
-(void)testMethod
{
NSLog(@"i am TestModelHelper1");
}
@end
@implementation TestModelHelper2
-(void)testMethod
{
NSLog(@"i am TestModelHelper2");
}
@end
运行可看到消息转发日志