iOS之09-特有语法
2016-05-11 16:41
447 查看
1、分类 - Category
如何在不改变原来类模型的前提下,给类扩充一些方法?
有2种方式: 继承; 分类(Categoty)。
2> 格式
分类的声明
@interface 类名(分类名称)
// 方法声明
@end
分类的声明
@implementation 类名(分类名称)
// 方法声明
@end
分类名一般以模块名命名
当一个类特别庞大,并且具有不同的功能,我们可以一个功能写在一个分类中,更有利于团队开发。
分类方法实现中可以访问原来类中的成员变量
分类可以重新实现原来类中的方法,但是会覆盖掉原来的方法,会导致原来的方法没法再使用
分类的优先级最高,方法调用时,优先到分类中查找,然后再去原来类中查找,最后再去父类中找
多个Category中如果实现了相同的方法,只有最后一个参与编译的才会有效
查看编译顺序:点击工程名,build phases -> Compiles Sources
Class 类型的定义
typedef struct objc_class *Class
类名就代表着类对象,每个类只有一个类对象
先加载父类,再加载子类;也就是先调用父类的 +load ,再调用子类的 +load
先加载原始类,再加载分类
不管程序运行过程有没有用这个类,都会调用 +load 方法
一个类只会调用一次 +initialize 方法,先调用父类的,再调用子类的
或者
Person *p = [Person new];
Class c2 = [p class]; // 对象方法
Person *p2 = [c new];
-description 决定了实例对象的输出结果,默认情况下,结果是:<类名:内存地址>
+description决定了类对象的输出结果,默认情况下,结果是:类名
4> 死循环陷阱
如果在 -description 方法中使用 NSLog 打印 self
5> NSLog打印增强
根据一个SEL对象就可以找到方法的地址,进而调用方法
SEL类型的定义
typedef struct objc_selector *SEL;
间接调用方法(performSelector: SEL)
1> 基本用途
分类:可以给某个类扩充一些方法(不修改原来的代码)如何在不改变原来类模型的前提下,给类扩充一些方法?
有2种方式: 继承; 分类(Categoty)。
2> 格式
分类的声明
@interface 类名(分类名称)
// 方法声明
@end
分类的声明
@implementation 类名(分类名称)
// 方法声明
@end
3> Category在 Xcode 7.2 创建方法
New File -> Objective-C File -> File为分类名,File Type选Category,class为创建分类的类分类名一般以模块名命名
4> 好处
当一个类特别庞大,并且具有不同的功能,我们可以一个功能写在一个分类中,更有利于团队开发。5> 使用注意
分类只能增加方法,不能增加成员变量分类方法实现中可以访问原来类中的成员变量
分类可以重新实现原来类中的方法,但是会覆盖掉原来的方法,会导致原来的方法没法再使用
分类的优先级最高,方法调用时,优先到分类中查找,然后再去原来类中查找,最后再去父类中找
多个Category中如果实现了相同的方法,只有最后一个参与编译的才会有效
查看编译顺序:点击工程名,build phases -> Compiles Sources
2、类的本质
1> 类也是个对象
其实类也是一个对象,是 Class 类型的对象,简称 "类对象"Class 类型的定义
typedef struct objc_class *Class
类名就代表着类对象,每个类只有一个类对象
2> +load 和 +initialize
① +load
当程序启动的时候会加载所有的类和分类,并调用所有的类和分类的 +load 方法先加载父类,再加载子类;也就是先调用父类的 +load ,再调用子类的 +load
先加载原始类,再加载分类
不管程序运行过程有没有用这个类,都会调用 +load 方法
② +initialize
在第一次使用某个类时(比如创建对象等),就会调用一次 +initialize 方法一个类只会调用一次 +initialize 方法,先调用父类的,再调用子类的
3> 获取类对象的2种方式
Class c = [Person class]; // 类方法或者
Person *p = [Person new];
Class c2 = [p class]; // 对象方法
4> 类对象调用类方法
Class c = [Person class];Person *p2 = [c new];
3、description 方法
1> -description 方法
使用NSLog和%@输出某个对象时,会调用对象的 -description 方法-description 决定了实例对象的输出结果,默认情况下,结果是:<类名:内存地址>
2> +description 方法
使用NSLog和%@输出某个类对象时,会调用对象的+description 方法+description决定了类对象的输出结果,默认情况下,结果是:类名
3> 修改 NSLog 的默认输出
重写 -description 或者 +description 方法即可 4> 死循环陷阱
如果在 -description 方法中使用 NSLog 打印 self 5> NSLog打印增强
1 Person *p = [[Person alloc] init]; 2 3 // 指针变量地址 4 NSLog(@"%p", &p); 5 // 对象的地址 6 NSLog(@"%p", p); 7 // <类名:对象地址> 8 NSLog(@"%@", p); 9 // 输出代码所在行数 10 NSLog(@"%d", __LINE__); 11 12 // 输出源文件的路径 13 // NSLog输出C语言字符串的时候,不能有中文 14 // NSLog(@"%s", __FILE__); 15 printf("%s\n", __FILE__); 16 17 // 输出当前函数名 18 NSLog(@"%s", __func__);
4、SEL
1> 方法的存储位置
每个方法都有一个与之对应的SEL类型的对象根据一个SEL对象就可以找到方法的地址,进而调用方法
SEL类型的定义
typedef struct objc_selector *SEL;
2> SEL对象的创建
SEL sel = @selector(test); SEL s = NSSelectorFromString(@"test"); // NSSelectorFromString将字符串转为SEL类型的数据
3> SEL对象的其他用法
将SEL对象转为NSString对象// 将SEL对象转为NSString对象 NSString *str = NSStringFromSelector(@selector(test));
间接调用方法(performSelector: SEL)
1 // 间接调用对象p的方法 2 // 不带参数的方法 3 SEL sel = @selector(test2); 4 [p performSelector:@selector(test2)]; 5 6 // 带参数的方法 7 [p test3:@"abc"]; 8 [p performSelector:@selector(test3:) withObject:@"a456"];
4> _cmd
_cmd 代表着当前方法1 - (void)test2 { 2 3 // _cmd 代表着当前方法 4 NSString *str = NSStringFromSelector(_cmd); 5 6 // 会造成死循环 7 // [self performSelector:_cmd]; 8 9 NSLog(@"test2----%@", str); 10 }
相关文章推荐
- iOSDay15之OC集合
- iOSDay13之OC NSString类
- iOS之08-核心语法
- iOSDay12之OC属性和点语法
- iOSDay11之OC继承
- iOS之07-三大特性之多态 + NSString类
- iOSDay10之OC类和对象
- iOS之06-三大特性之继承
- iOS之05-三大特性之封装
- iOS之04-方法的声明和实现
- iOS之03-类的合理设计
- iOS之02-第一个OC的类
- iOS之01-基本语法
- tableView侧滑显示多个按钮(IOS 8.0)
- iOS-界面跟随键盘移动
- iOS开发 根据某个日期计算是星期几
- iOS NSTimer 的使用
- iOS的动态创建实例方法和实现消息转发
- IOS数据存储之文件沙盒存储
- iOS开发tableView实现单选和复选