1、静态和动态概念
静态:在程序编译阶段就能确定数据类型和所调用的方法;
动态:将程序在编译阶段就能确定数据类型和所调用的方法,推迟到了运行时。
2、OC的动态特性表现为了三个方面:动态类型、动态绑定、动态加载
- (1)动态类型—— id 类型
像int、NSString这些内置的明确的基本类型都属于静态类型,静态类型在 编译的时候就能被识别出来,所以当程序发生了类型不对应,编译器就会发出警告。而动态类型就编译器编译的时候是不能被识别的,要等到运行时(run time),即程序运行的时候才会根据语境来识别。OC 的 id 类型就是一个动态类型
id obj = someInstance;
if ([obj isKindOfClass:someClass]) {
someClass *classSpecifiedInstance = (someClass *)obj;
}
- (2)动态绑定—— @selector/SEL
在静态语言,比如 c++,在编译的时候就已经将将要调用的函数的函数告诉编译器了,没有这个函数编译就通不过。
OC的动态绑定可以先跳过编译,到运行的时候才动态地添加函数调用,决定要调用什么方法,需要传什么参数。
/*
* 比如给button 添加一个点击方法,但ViewController 中不定义这个方法,编译 OK,
* 点击按钮的时候就会报错-[ViewController oneMethod:]: unrecognized selector sent to instance
*/
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
[button addTarget:self action:@selector(oneMethod:) forControlEvents:UIControlEventTouchUpInside];
- (3)动态加载—— @2x
根据需求加载所需要的资源,这点很容易理解,对于iOS开发来说,基本就是根据不同的机型做适配。最经典的例子就是在Retina设备上加载@2x的图片,而在老一些的普通屏设备上加载原图。
3、对动态绑定@selector(selector) 的补充
点进去会发现selector 是 SEL 类型的 @property (nonatomic, assign) SEL selector;
SEL变量是一个整数,本质就是类方法的编号(函数地址),@selector()就是取类方法的编号,返回的结果是一个SEL类型。
@interface Person : NSObject
+ (void)test1;
- (void)test2;
@end
// 根据.h文件中定义的Person类和方法 执行完这行代码 在内存中如下
Person *person = [[Person alloc] init];
Person 类的内存布局
方法的存储位置
- 在内存中每个类的方法都存储在类对象中
- 每个方法都有一个与之对应的SEL类型的数据
- 根据一个SEL数据就可以找到对应的方法地址,进而调用方法
- SEL类型的定义: typedef struct objc_selector *SEL










网友评论