1.autorelease的用法
1、自动释放池及autorelease介绍
(1)在iOS程序运行过程中,会创建无数个池子,这些池子都是以栈结构(先进后出)存在的。
(2)当一个对象调用autorelease时,会将这个对象放到位于栈顶的释放池中 。
2、为什么会有autorelease?
OC的内存管理机制中比较重要的一条规律是:谁申请,谁释放。
但有些情况下,开发者并不能确定某些对象何时释放。这时候就需要自动释放池。
它的好处是:
(1)不需要再关心对象释放的时间 ;
(2)不需要再关心什么时候调用release ;
3,autorelease的使用注意:
(1),只有在自动释放池中调用了autorelease方法的对象,才会被放进池子里面;
(2),自动释放池中不适宜放占用内存比较大的对象,尽量避免对大内存使用该方法,对于这种延迟释放机制,还是尽量少用 ;
(3),不要把大量循环操作放到同一个 @autoreleasepool 之间,这样会造成内存峰值的上升 ;
(4),池子释放的时候,只会对它里面的对象做一次release操作。
2.ARC下内存管理
1,ARC介绍及入门
1, Automatic Reference Counting,自动引用计数,即ARC。
2、指针分类
(1)强指针:默认的情况下,所有的指针都是强指针,关键字strong
(2)弱指针:_ _weak关键字修饰的指针
声明一个弱指针如下:
_ _weak Person *p;
3、ARC工作原理及判断准则 :
ARC是Objective-C编译器的特性,而不是运行时特性或者垃圾回收机制,ARC所做的只不过是在代码编译时为你自动在合适的位置插入release或autorelease。
4,ARC的判断准则:
只要还有一个强指针变量指向对象,对象就会保持在内存中。
只要没有强指针指向对象,对象就会被释放。
注意:当使用ARC的时候,暂时忘记“引用计数器”,因为判断标准变了
2,ARC对象管理
总结:
1,当栈区的指向对象的局部变量随着代码块的结束,而被释放;那么,对象就没有了强指针引用了,所以也被释放。
2,当对象被指定为__week的弱指针时,对象也被释放。
ARC下循环引用:
解决方案:循环引入的对象中其中一个对象设置为strong ,另一个设置为weak
ARC下@property参数
strong : 用于OC对象, 相当于MRC中的retain
weak : 用于OC对象, 相当于MRC中的assign
assign : 用于基本数据类型, 跟MRC中的assign一样
copy : 一般用于NSString, 跟MRC中的copy一样
在ARC情况下解决”循环retain”的问题:
@property一边用strong,一边用weak。
3,ARC使用注意
1、ARC特点总结
(1)不允许调用release,retain,retainCount
(2)允许重写dealloc,但是不允许调用[super dealloc]
(3)@property的参数:
strong:相当于原来的retain(适用于OC对象类型),成员变量是强指针
weak:相当于原来的assign,(适用于oc对象类型),成员变量是弱指针
assign:适用于非OC对象类型(基础类型)
2、ARC使用注意事项
1)ARC中,只要弱指针指向的对象不在了,就直接把弱指针做清空(赋值为nil)操作。
2)__weak Person *p=[[Person alloc] init];//不合理,对象一创建出来就被释放掉,对象释放掉后,ARC把指针设置为nil。
3)ARC中在property处不再使用retain,而是使用strong,在dealloc中不需要再[super dealloc]。
@property(nonatomic,strong)Dog *dog;
// 意味着生成的成员变量_dog是一个强指针,相当于以前的retain。
4)如果换成是弱指针,则换成weak,不需要加_ _。
3、ARC模式下如何兼容非ARC的类 :转变为ARC的, -f-objc-arc
非ARC模式下如何兼容ARC的类 :转变为非ARC -fno-objc-arc
4,将MRC转换为ARC
其实就是将一些代码删掉。
3.分类(category)
1,category概念介绍
一、Category有很多种翻译: 分类 \ 类别 \ 类目 (一般叫分类)
Category是OC特有的语法;
二、类别的作用 :
在不修改原有的类的基础上增加新的方法
一个庞大的类可以分模块开发
一个庞大的类可以由多个人来编写,更有利于团队合作
三、使用类别的目的
1)对现有类进行扩展:
比如,你可以扩展Cocoa touch框架中的类,你在类别中增加的方法会被子类所继承,而且在运行时跟其他的方法没有区别。
2)作为子类的替代手段: 不需要定义和使用一个子类,你可以通过类别直接向已有的类里增加方法。
3)对类中的方法归类: 利用category把一个庞大的类划分为小块来分别进行开发,从而更好的对类中的方法进行更新和维护。
2,category使用
一、声明和实现一个类别
1、在.h文件中,声明类别:
@interface ClassName (CategoryName)
NewMethod; //在类别中添加方法 ,不允许在类别中添加变量
@end
说明:
声明类别格式
1)新添加的方法必须写在 @interface 与@end之间
2)ClassName 现有类的类名(要为哪个类扩展方法)
3)CategoryName 待声明的类别名称
4)NewMethod 新添加的方法
2、在.m文件中(也可以在.h中实现),实现类别:
@implementation ClassName(CategoryName)
NewMethod
@end
说明:
实现类别格式
1)新方法的实现必须写在@implementation与@end之间
2)ClassName 现有类的类名
3)CategoryName 待声明的类别名称
4)NewMethod 新添加的方法的实现
二、分类的使用注意:
1)分类只能增加方法, 不能增加成员变量、@property(可能编译不报错,但是运行有问题)
2)分类可以访问原来类中的成员变量
3)如果分类和原来类出现同名的方法, 优先调用分类中的方法, 原来类中的方法会被忽略
举例:现在我们有一个类叫MyClass,
它有一个实例方法:myPrint,待会我们可以在扩展后调用它.我们要在不增加子类,不修改MyClass类的情况下增加一个HelloWorld的方法
1.command+n新建文件
2.Class的类是MyClass,选对了哦
这样Xcode就帮你创建了MyClass+HelloWorld.h 和 MyClass+HelloWorld.m这两个 文件了。
3.那么我们现在添加一个HelloWorld方法。看看实现后的代码如下:
那的Category的使用场景有那些呢:
1、类包含了很多个方法实现,而这些方法需要不同团队的成员来实现
2、当你在使用基础类库中的类时,你不想继承这些类而只想添加一些方法时。
Category能实现上面的需求,当然也有使用Category是需要注意的问题:
1、Category可以访问原始类的实例变量,但不能添加实例变量,如果想添加变量,那就通过继承创建子类来实现。
2、Category可以重载原始类的方法,不大不推荐这么做,这样会覆盖掉原始类的方法。如果确实要重载,那就通过继承创建子类来实现。
3、和普通接口有所区别的是,在Category的实现文件中的实例方法只要你不去调用它你可以不用实现所有声明的所有方法。
3.非正式协议
非正式协议就是给NSObject类创建的类目(分类)叫做非正式协议, 非正式协议一般不需要进行实现,一般在子类中进行方法的重写。
4.延展:匿名的类目;
主要的使用意义是在类的.m文件中定义类的私有;
//延展的声明 //类目的声明
@interface Student () @interface Student(Creation)
@end @end
延展中定义的方法不能被继承也不能被子类访问;
4.block的学习
1,block简单介绍
block的基本概念
Block对象是一个C级别的语法和运行机制。它与标准的C函数类似,不同之处在于,它除了有可执行代码以外,它还包含了与堆、栈内存绑定的变量。
因此,Block对象包含着一组状态数据, 这些数据在程序执行时用于对行为产生影响。
你可以用Block来写一些可以传到API中的函数语句,可选择性地存储,并可以使用多线程。 作为一个回调,Block特别的有用,
因为block既包含了回调期间的代码,又包含了执行期间需要 的数据。
由于Objective-C 和 C++ 都是衍生自 C,block被设计为可同时兼容这三种语言。
2,block具体用法
1) block最简单形式
定义格式:
void (^block名)() = ^{代码块;}
使用格式:
block名();
2) block带有参数的block的定义和使用
格式:
void (^block名称)(参数列表)
= ^ (参数列表) { // 代码实现; }
3) 带有参数和返回值的block
格式:
返回类型 (^block名称)(参数列表)
= ^ 返回类型 (参数列表) { // 代码实现; }
4)利用typedef定义block类型(和指向函数的指针很像)
格式:
typedef 返回值类型 (^block变量名)(参数类型列表);
3.block使用注意
1)在block内部可以访问block外部的变量 ;
2)在block内部不可以修改block外部的变量
默认情况下,Block内部不能修改外部的局部变量 ;
3)给局部变量加上__block关键字,则这个局部变量可以在block内部进行修改。