iOS之09-特有语法

1、分类 - Category

 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 }

 

posted @ 2016-03-26 19:08  墨隐于非  阅读(186)  评论(0编辑  收藏  举报