A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 龙@程序员 中级黑马   /  2014-12-19 22:59  /  562 人查看  /  0 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

#import 的用途:
1.跟#include一样,拷贝文件的内容
2.能够自动防止文件的内容被重复拷贝      @class 和 #import 的区别:
    * 使用 @class 类名:就可以引用一个类,说明它是一个类。
* #import 方式会包含被引用类的所有信息,包括被引用类的变量和方法; @class 方式只是告诉编译器在 A.h 文件中 B *b 只是类的声明,具体这个类里有什么信息,这里不需要知道,等实现文件中真正要用到时,次才会真正去查看 B 类中的信息。
* 如果有上百个头文件都 #import 了同一个文件,或者这些文件一次呗 #import ,那么一旦最开始的头文件稍有改动,后面引用到这个文件的所有类都需要重新编译一遍,这样的效率会很低。相对来讲,使用 @class 方式就不会出现这种情问题了。
* 在 .m 实现文件中,如果需要引用到被引用类的实体变量或者方法时,还需要使用 #import 方式引入被引用类。1.空指针
1> 没有存储任何内存地址的指针就称为空指针(NULL指针)
2> 空指针就是被赋值为0的指针,在没有被具体初始化之前,其值为0。
下面两个都是空指针:
  • Student *s1 = NULL;
  • Student *s2 = nil;

[color=rgb(177, 8, 0) !important]复制代码

2.野指针
"野指针"不是NULL指针,是指向"垃圾"内存(不可用内存)的指针。野指针是非常危险的。




类的本质
  • <p><p>//类本身也是一个对象,是个Class类型的对象  ,简称 类对象!类名就代表类对象</p><p>
  • Person *p = [[Person alloc] init];
  • /*
  • 利用Class创建一个类对象 Person</p><p>利用 Person类对象 创建 Person类型的对象;
  • */</p>

[color=rgb(177, 8, 0) !important]复制代码

怎么获取类对象:
1、Class c = [p class]; // 利用实例对象的class方法获取内存中得类对象!
2、Class c1 = [Person class]; // 通过类对象的方法class也能获取类对象!其实类名就代表着类对象。

当程序启动的时候就会加载一次项目中所有的类,类加载完毕后就会调用一次一个类方法: + (void)load;
当第一次使用这一个类的时候,就会调用 + (void)initialize方法
注意优先顺序是先加载父类,然后加载子类最后加载分类
load方法加载顺序: 父类——>子类——>分类
initialize方法顺序: 分类——>(假如没有分类才会调用,因为分类会覆盖父类的这个方法才调用父类的)父类->子类
分类启动加载的时候也会调用+ (void)load ,在第一次使用的时候也会调用+ (void)initialize;
1、当程序启动时,就会加载项目中所有的类和分类,而且加载会用每个类以及分类的+load方法;
2、当第一次使用某个类的时候就会调用当前类的 + initialize方法来初始化这个类;
3、+load先加载父类再加载子类最后加载分类; 第一次使用的时候也是先初始化父类再初始化子类;
4、当类初始化的时候,假如有分类那么优先调用分类的+ initialize方法(假如有多个分类那么就会调用最后一个参与编译的分类的+ initialize方法);而加载的时候,则类和分类都会加载+load方法。
//注意!+load方法和+initalize方法都只会调用一次,在类加载的时候,分类是最后加载的!
利用重写 + initalize 可以监听类第一次初始化,而且可以在利用重写 +initalize可以在第一次使用这个类的时候做一些事情!
例如:
  • @implementation Person
  • + (void)initialize
  • {
  •     NSLog(@"你第一次使用我啦!");
  • }
  • @end

[color=rgb(177, 8, 0) !important]复制代码
当第一次使用这个Person类的时候,就会打印:你第一次使用我啦!
SEL
在类中每个方法都有对应的SEL类型的对象;可以根据SEL对象就可以找到方法的地址,进而调用这个方法;
  • <p><p>Person *p = [[Person alloc] init]; // Person有一个对象方法 test2</p><p>[p test2]; // 调用 test2方法</p><p>// 解析:
  • //把test2包装为一个SEL类型的数据
  • //根据SEL数据找到对应的方法地址
  • //根据方法地址调用对应的方法
  • //下面的例子和上面的效果一样
  • int main()
  • {
  •    Person *p = [[Person alloc] init];</p><p>  //间接访问test2方法;
  •   [p performSeltor:@selectr(test2)];</p><p>}</p>

[color=rgb(177, 8, 0) !important]复制代码

2.SEL对象的创建
SEL s = @selector(test);
SEL s2 = NSSelectorFromString(@"test"); // 把一个字符串数据传进去转化为一个SEL数据
NSString *s3 = NSStringFromSelector(s2);// 把一个SEL数据转化为一个字符串
注意:利用@selector(test)查找方法储存地址的时候,要是有参数一定要加冒号“:”,因为冒号也是函数的一部分
每个方法的的内部都有一个SEL数据,_cmd  它代表着当前方法
比如:
  • - (void)test
  • {
  •   //////
  •   //在这个方法中 _cmd == @selctor(test) 这个表达式为真!!!
  • }

[color=rgb(177, 8, 0) !important]复制代码

注意!!在方法中绝对不能写 [sel performSelector:_cmd];
       这句话会导致死循环!!
还有SEL没有支持直接传基本型数据(如 int、double等等)的方法,只能传对象和指针!!

0 个回复

您需要登录后才可以回帖 登录 | 加入黑马