#program mark - 01 @class关键字 [掌握] 1.头文件循环引用的前提 1.如果使用#import指令,在A类中导入B类的头文件,同时在B类中导入了A类的头文件 2.在A类或者B类中,使用到了导入的类型 以上两点同时存在,才会出现头文件循环引用的问题
2.如何解决循环引用的问题 1.在A类的头文件中使用#import,在B类的头文件中使用@class关键字 2.在B类的.m文件中,使用#import导入A类的头文件,这样才能正常使用A类
3.@class 不是一个预处理指令,它的作用仅仅是声明有这样一个类,可以使用该类型 但是@class并不会拷贝类的头文件到写指令的位置,所以并不知道类中有哪些内容 在需要使用类中的内容的时候,还需要使用#import指令导入该类的头文件
4.请说出#inclue #import @class的区别 #include是一个预处理指令,会把文件内容拷贝到写指令的地方 #import是一个预处理指令,是#include的增强版,可以避免头文件的重复包含 @class是一个关键字,而不是预处理指令,作用是声明有这样一个类,但是并不会导入类的头文件
5.@class不需要拷贝文件,所以性能比#import 可以在头文件中只使用@class声明类,然后在.m中,当具体使用到某个类的时候,再去#import头文件,这样做可以提高性能 在公司中根据之前老员工的编程习惯和代码习惯来模仿就可以了
#program mark - 02 循环retain [掌握] 循环引用:在A对象中拥有B对象,在B对象中拥有A对象,如果两端都使用retain的内存管理策略,会导致A和B都无法释放,造成内存泄漏 解决方案:一端用retain,另外一端用assign. 注意:用assign的一端不要在dealloc中释放对应的成员变量
MRC中,当对象的引用计数器为0的时候,会释放对象,同时由系统调用对象的dealloc方法 引用计数器=0 -> 对象销毁 -> dealloc
#program mark - 03 自动释放池的使用 [掌握] 1.什么是自动释放池 // 有一个NSAutoreleasPool类,用来描述自动释放池
@autoreleasepool { }
自动释放池就是一对大括号包裹的作用域,只不过这个作用域前面有一个@autoreleasepool修饰
2.和普通的作用域的区别 1.比普通作用于多了一个@autoreleasepool修饰符 2.自动释放能够在销毁(作用域结束)的时候,自动的对其中调用过autorelease方法的对象,发送release消息
3.作用: 防止对于使用alloc \ new 创建的对象,忘记手动调用release方法,而出现内存泄漏的问题
4.注意点 一个对象写在@autoreleasepool并不代表该对象会自动释放,还需要调用autorelease方法,把对象添加到自动释放池中,这样才会自动release
#program mark - 04 使用自动释放出的七大注意 [掌握] 1.需要通过自动释放池释放的对象,并不需要池中创建,只要保证是在当前自动释放池中调用对象的autorelease方法即可 2.autorelease并不是立刻给对象发送release消息,只是把对象添加到当前自动释放池中,当当前自动释放池销毁的时候,会自动的给对象发一条release 3.给对象发送release消息之后,对象不一定会销毁. 在MRC环境下,判断对象是否销毁,只有一个原则,就是对象的引用计数器是否为0 4.不要给对象多次调用autorelease,可能会造成野指针错误 5.自动释放池可以嵌套,对象在哪个自动释放中调用autorelease方法,那就会在该自动释放池销毁的时候,给对想发送release消息
自动释放池的最常见用法:(自动释放池存在的意义) 帮助我们在使用new或者alloc创建对象之后,不需要手动调用release
#program mark - 05 自动释放池的规范 [掌握] 1.在定义类的时候,需要定义一个和类同名的类方法,用来返回一个对象,作用就是为了快速创建一个指定值对象 2.在MRC中,只有看到new\alloc\retain的时候,才需要调用release,所有使用类方法创建的对象,不应该在外部release 3.在类方法内部返回对象之前,需要把对象添加到自动释放池中
4.规范:创建类需要提供类方法返回一个对象,而且需要在此方法内部调用autorelease方法,把对象添加到自动释放池中,苹果内部也是这样做的
#program mark - 07 微博练习 [掌握] [讲] 1.返回对象的类方法,在对象返回之前需要调用autorelease,把对象添加到自动释放池中 2.使用@class防止头文件的循环依赖 3.注意对象之间的循环retain
// 从ARC开始,对MRC的东西全都不需要了 #program mark - 08 ARC机制的概述 [掌握] 1.ARC是一个编译器特性,2011年iOS5开始出现的 编译器在编译代码的时候,会自动的在合适的位置插入内存管理的代码(release\retain\autorelease) 在ARC机制下不用使用内存管理相关的方法 release\retain\autorelease\retainCount\dealloc
2.ARC本质上是基于MRC,从根本上来说,还是需要根据引用计数器判断对象是否需要释放 但是这个过程别编译器屏蔽起来了,不需要程序员来做,所以可以认为,在ARC机制中,没有引用计数器的概念
3.ARC内存管理的原则 只要一个对象没有强指针指向,那么就会释放
4.对指针的修饰符 1.__strong修饰的指针是强指针,默认情况下只要定义一个指针变量,就是强指针 2.__weak修饰时指针是弱指针 强指针和弱指针在操作对象方法没有任何的区别 唯一的区别:作为ARC机制下,判断对象是否需要回收的标准
#program mark - 09 第一个ARC程序 [掌握] 1.Xcode6之后,默认创建的项目都是ARC环境 2.在ARC中,可以重写dealloc,但是在最后不要调用[super dealloc];
3.没有强指针指向任何对象 1.指向对象的所有强指针在作用域结束之后被回收了 2.指向对象的所有强指针都指向了nil
4.创建对象的时候,千万不要使用弱指针指向,没有任何意义,编译器会报警告 __weak HMPerson *p = [HMPerson new];
#program mark - 10 @property参数strong与weak [掌握] MRC的时候 @property retain assign ARC内存管理相关的参数
1.ARC机制下,setter方法中直接赋值即可,不需要做其它事情,所以retain没有意义 2.ARC机制下,使用@property的时候,只需要考虑它自动生成的成员变量是强指针还是弱指针 两个新的参数 strong,代表@property自动生成的私有成员变量是强指针类型的 weak,代表@property自动生成的私有成员变量是弱指针类型的
3. 在ARC机制下,如果成员变量是OC对象,大多数情况下,使用strong,有一些特殊情况需要使用weak 如果成员变量是非OC对象,使用assign
#program mark - 11 ARC机制下的循环引用 [掌握] [讲] 出现的问题:当A对象有一个属性是B对象,B对象中有一个属性是A对象,如果在两端都使用strong,那么会造成对象的循环引用,导致两个对象都无法释放 解决方案:一段使用strong,另外一端使用weak即可
MRC中因为使用reatin导致循环引用 ARC中因为使用strong导致循环引用
#program mark - 12 @property参数总结 [掌握] strong weak retain assign
#program mark - 13 弱指针在对象被回收以后自动设置为nil [掌握]
如果在MRC中,当对象释放之后,再通过指向该对象的指针给该对象发送消息,就会造成野指针错误
使用__weak关键字的好处: 如果在ARC中,当weak指针指向的对象释放之后,会自动把该指针指向nil,避免野指针错误
#program mark - 14 MRC和ARC的兼容 [掌握]
MRC手动内存管理:手动管理对象的引用计数器 release\reatin ARC自动内存管理:编译器会自动帮助我们管理对象的引用计数器
目前在公司中,比较主流的新的项目,肯定都是ARC的 但是可能会存在一些老的项目
老的MRC项目里面 可能会用到一些功能(第三方框架:别人写好的功能的集合) 可能会开发新的项目,可能有一些老的第三方框架,其有一个功能非常好用,但是没有推出ARC的版本
ARC和MRC混合开发的情况...
1.如果在ARC的环境下,想要正常编译MRC的代码,那么需要通过编译器参数,单独告诉编译器,包含MRC代码的.m文件不要以ARC的形式进行编译 -fno-objc-arc
2.如果在MRC的环境下,想要正常编译ARC的代码,那么需要通过编译器参数,单独告诉编译器,包含ARC代码的.m文件不要以MRC的形式进行编译 -fobjc-arc
#program mark - 15 MRC程序转换为ARC程序 [掌握]
1.可以通过Xcode的Convert功能,把MRC的项目转换成ARC的项目 2.它的做法其实就是把MRC中相关的内存管理代码去掉 3.这种方式不靠谱,可能会失败,成功率比较低,不推荐使用
总结: MRC和ARC混合开发的解决方案 1.使用Xcode自带的转换工具,把MRC转换成ARC,但是有风险 2.使用编译器标记 3.静态库:在生成静态库的时候,就会把文件先编译好 4.条件编译: #if !__has_feature(objc_arc) [array release]; #endif 可以使用条件编译,判断当前编译器的特性,如果是MRC,那么就使用内存管理的代码,如果是ARC就不使用内存管理的代码
4.Product中的工具Analyze,静态检测工具,可以根据语法检测代码是否存在问题
// 新的语法 #program mark - 16 分类的简单使用 [掌握] 1.分类是什么: OC中特有的yufa 2.分类的作用: 将1个类分为多个模块,将类似的方法放在同一个模块中,这可以方便我们后期对类进行维护和管理 3.格式 @interface HMPerson (base)
- (void)eat;
@end
@implementation HMPerson (base)
- (void)eat { }
@end
4.如果需要给一个类增加方法,有几种方式? 1.直接修改原来的类 2.继承,成为该类的子类 3.使用分类:在不改变原来类以及成为其子类的情况下,给该类扩展方法
5.如果在@interface使用@property,会做3件事情 1.生成一个_开头的私有成员变量 2.针对该成员变量生成setter和getter的声明 3.针对该成员变量生成setter和getter的实现
6.如果在分类中使用@property会做几件事情? 只会生成setter和getter的声明,不会生成_开头的私有成员变量,以及不会生成setter和getter的实现
|