发送消息
消息传递是OOP中的一个基础概念,是用于调用对象中方法的机制,接受消息的对象(接收器)会在运行时决定调用其实例的那个方法,实例方法可以访问对象的实例变量和实例方法。
Objective-C通过语言级的功能增加了对对象消息传递的支持,使你可以再运行时决定滴啊用哪个方法,甚至还可以再运行时更改方法的实现代码。
消息转发机制
当对象收到与其方法集不匹配的消息时,通过消息转发机制可以使对象执行用户预先定义的处理过程。消息转发使对象能够在收到无法识别的消息时执行各种逻辑,如将消息发送给能够作出回应的其他接收器,将所有无法识别的消息都发送给同意接收器,或者不执行处理过程也不使程序抛出运行时错误。
对象消息
在OOP术语中,消息传递是指一种在对象之间发送和接受消息的通信模式,在Objective-C中,消息传递用于调用类和类实例的方法。

接收器是消息的目的地,而消息本身由选择器和相应的输入参数构成。

如上图展示了Objective-C运行时系统通过动态类型和动态绑定,将消息与方法对应起来的方式
SEL类型
选择器类型SEL
是一种特殊的Objective-C数据类型,是用于在编译源代码时替换选择器值的唯一标识符。所有具有相同选择器值的方法都拥有相同的SEL
标识符。Objective-C运行时系统会确保每个选择器标识符的唯一性。可以使用关键字@selector
创建SEL
类型的变量。
SEL method = @selector(myMethod);
方法签名
编译器会将
[接收器 消息]
形式的对象消息,转换为声明中含有方法签名的(ANSI)C函数调用语句,为了生成正确的消息传递代码,编译器需要获得选择器值和方法签名。编译器可以从对象消息表达式中轻松提取选择器,为了确定争取的方法签名,编译器会根据已解析的方法声明进行猜测,如果找不到方法签名,或从方法声明获得的方法签名与运行时实际执行的方法不匹配,就会出现方法签名不匹配的情况,会导致从编译器警告到运行时错误的各种问题。
动态类型
运行时系统通过动态类型功能,可以再运行程序时决定对象的类型,因而可以使运行时因素能够在程序中指定使用哪个对象。Objective-C既支持静态类型也支持动态类型。当静态方法设置变量的类型时,变量的类型就由它的声明决定。
id数据类型是一种Objective-C独有的数据类型,其变量可以存储任何数据类型的Objective-C对象,而不论该对象是哪种类的实例。
动态绑定
动态绑定
是指在运行程序时将消息与方法对应起来的处理过程。
动态绑定
是Objective-C的一种继承特性,它不需要任何特定的API,使用动态绑定甚至可以将消息选择器设置为在运行程序时确定的变量。
动态方法决议
使用动态方法决议能够以动态方法实现方法,使用Objective-C中的
@dynamic
指令,可以告知编译器与属性关联的方法会以动态方式实现。
NSObject
类中含有+ (BOOL)resolveInstanceMethod:(SEL)sel
和+ (BOOL)resolveClassMethod:(SEL)sel
方法,他们能够以动态方式分别为指定的实例和类方法选择器添加实现代码,你可以重写这些方法。以动态方式实现实例/类方法。
以动态方式实现方法
+ (BOOL)resolveInstanceMethod:(SEL)sel{
NSString *method = NSStringFromSelector(sel);
if ([method hasPrefix:@"absoluteValue"]) {
class_addMethod([self class], sel, (IMP)absoluteValue, "@@:@");
NSLog(@"method %@ class %@",method,NSStringFromClass([self class]));
return YES;
}
return [super resolveInstanceMethod:sel];
}
id absoluteValue(id self, SEL _cmd, id value){
NSInteger intval = [value integerValue];
if (intval < 0) {
return [NSNumber numberWithInteger:intval*5];
}
return value;
}
在main.m中
SEL selectors = NSSelectorFromString(@"absoluteValue:");
id sum = [p performSelector:selectors withObject:@2];
NSLog(@"%@",sum);
动态加载
Objective-C程序通过动态加载功能可以根据需要加载可执行代码和源代码,无需再穷程序时就加载程序的所有组件,可以执行代码可以含有新的类,并使这些新类在运行程序是整合到整个程序中。
内省
Foundation框架中NSObject类的API含有非常多用于执行对象内省的方法,使用这些方法能够以动态方式在程序运行时查询下列信息:
1.与方法有关的信息
2.测试对象的继承性、行为和一直的信息
BOOL isPerson = [p isKindOfClass:[Person class]];
//语句检查对象是否遵守指定的协议
BOOL respons = [p respondsToSelector:@selector(absoluteValue:)];
//为选择器提取方法签名
NSMethodSignature *signature = [p methodSignatureForSelector:@selector(absoluteValue:)];
网友评论