iOS开发之oc(十)--类的本质、description、SEL
(一)类的本质
1.类也是个对象
其实类也是一个对象,是Class类型,简称“类对象”。
// Class类型的定义 typedef struct objc_class *Class; // 类名就代表着类对象,每个类只有一个类对象
2.+load和+initialize
-
+load
> 在程序启动的时候会加载所有的类和分类,并调用所有类和分类的+load方法
>先加载父类,再加载子类;也就是先调用父类的+load,再调用子类的+load
>先加载元原始类,再加载分类
>不管程序运行过程有没有用到这个类,都会调用+load加载
-
+initialize
>在第一次使用某个类时(比如创建对象等),就会调用一次+initialize方法
>一个类只会调用一次+initialize方法,先调用父类的,再调用子类的
代码示例 // 当程序启动的时候,就会加载一次项目中所有的类。类加载完毕后就会调用+load方法 + (void)load { NSLog(@"Person---load"); } // 当第一次使用这个类的时候,就会调用一次+initialize方法 + (void)initialize { NSLog(@"Person-initialize"); } @end
3.获取类对象的两种方式
Class c = [Person class]; // 类方法 // 或者 Person *p = [Person new]; Class c2 = [p class]; // 对象方法
4.类对象调用类方法
Class c = [Person class]; Person *p2 = [c new];
(二)description方法
(决定了实例对象/类对象的输出结果)
1. -description方法
使用NSLog和%@输出某个对象时,会调用对象的-description方法,并拿到返回值进行输出
1. + description方法
使用NSLog和%@输出某个类对象时,会调用类对象+description方法,并拿到返回值进行输出
2. 修改NSLog的默认输出
问题出现
int main() { Person *p = [[Person alloc] init]; NSLog(@"%@",p); return 0; } 输出为:<Person: 0x1001033b0> 是个地址,要想输出具体内容
重写-description或者+description方法即可
3. 死循环陷阱
如果在-description方法中使用NSLog打印self
(三)SEL
/* SEL其实是对方法的一种包装,将方法包装成一个SEL类型的数据,去找对应的方法地址。 找到方法地址就可以调用方法 其实消息就是SEL
原理 // 1.把某个方法例如test包装成SEL类型的数据
// 2.根据SEL数据找到对应的方法地址
// 3.根据方法地址调用对应的方法
*/
1.方法存储的位置
>每个类的方法列表都存储在类对象中
>每个方法都有一个与之对应的SEL类型的对象
>根据一个SEL对象就可以找到方法的地址,进而调用方法
>SEL类型的定义
typedef struct objc_selector *SEL;
2.SEL对象的创建
SEL s = @selector(test);
SEL s2 = NSSelectorFromString(@"test");
3.SEL对象的其他用法
代码示例
调用方法有两种途径: 1)直接通过方法名 [p test2] 2)传入方法对应的SEL去找方法地址 // 间接调用test方法 [p performSelector:@selector(test)]; 3)对象方法要传(带)参时 [p test:@"123"]; 等同下面( SEL的创建 SEL s = @selector(test:); ) [p performSelector:@selector(test:) withObject:@"456"]; 1>把字符串变成SEL SEL s = NSSelectorFromString(@"name"); 2>把SEL对象变成字符串NSString对象 _cmd代表着当前方法( _cmd==@selector(test); ) NSString *str = NSStringFromSelector(@selector(test)); NSString *str = NSStringFromSelector(_cmd); 补充: 每个方法内部都有一个隐藏的sel数据: _cmd(SEL)代表当前方法 死循环 - (void)test { // _cmd代表着当前方法 // 会引发死循环 [self performSelector:_cmd]; }