OC加强之ARC
Posted 忆缘晨风
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了OC加强之ARC相关的知识,希望对你有一定的参考价值。
1.
autorelease 的用法:
2.ARC快速入门:
ARC机制下注意事项:
1) 不允许调用对象的 release方法
2)不允许调用 autorelease方法
3)再重写父类的dealloc方法时,不能再调用 [super dealloc];
ARC分为了强弱指针:strong和weak(默认是强指针)
只要有强指针指向,对象就不会被释放,所以不存在内存泄漏的问题
3.分类:category
首先什么是分类?分类是干吗用的?
其实很简单:分类的定义就是在不改变原有类的基础上增加新的方法
注意事项:
1)分类中只能增加方法不能增加成员变量
2)分类中可以访问原有类的成员变量
3)如果分类中出现和原有类中同名的方法,优先调用分类中的方法,原有类中的方法会被屏蔽
4)如果有多个分类,每个分类都有同名的方法,此时应该怎么调用?
// 调用的是最后一个参与编译的分类文件的同名方法,跟引用头文件的顺序无关,跟创建顺序也无关
4.延展(extendsion)
所谓的扩展,其实就是为一个类添加额外的原来没有 的变量、方法或者合成属性(@property)。
类别与类扩展的区别:
1)类别中只能增加方法;
2)是的,你没看错,类扩展不仅可以增加方法,还可以增加实例变量(或者合成属性),只是该实例变量默认是私有类型的(作用范围只能在自身类,而不是子类或其他地方);
3)类扩展中声明的方法没被实现,编译器会报警,但是类别中的方法没被实现编译器是不会有任何警告的。这是因为类扩展是在编译阶段被添加到类中,而类别是在运行时添加到类中。
4)类扩展不能像类别那样拥有独立的实现部分(@implementation部分),也就是说,类扩展所声明的方法必须依托对应类的实现部分来实现。
5)定义在 .m 文件中的类扩展方法为私有的,定义在 .h 文件(头文件)中的类扩展方法为公有 的。类扩展是在 .m 文件中声明私有方法的非常好的方式。
5.block
1)block最简单形式
/** 定义时,把block当成数据类型
特点:
1. 类型比函数定义多了一个 ^
2. 设置数值,有一个 ^,内容是 {} 括起的一段代码
最简单的定义方式
void (^myBlock)() = ^ { // 代码实现; }
*/
void (^myBlock)() = ^ {
NSLog(@"hello");
};
// 执行时,把block当成函数
myBlock();
2) block带有参数的block的定义和使用
格式:
void (^block名称)(参数列表)
= ^ (参数列表) { // 代码实现; }
//定义有参数的block
void (^sumBlock)(int, int) = ^ (int x, int y) {
NSLog(@"%d", x + y);
};
//调用block
sumBlock(10, 20);
3) 带有参数和返回值的block
格式:
返回类型 (^block名称)(参数列表)
= ^ 返回类型 (参数列表) { // 代码实现; }
//定义有返回值和参数的block
int (^sumBlock2)(int, int) = ^ int (int a, int b) {
return a + b;
};
//调用有返回值的block
NSLog(@"%d", sumBlock2(4, 8));
4)利用typedef定义block类型
其实就是给block类型重命名用来替换这个类型更简化,起个别名
第一种是给无参无返回值的block起别名
第二种就是给有参无返回值block起别名
第三种是给有参有返回值的block起别名
6.block访问外部变量
1)在block内部是可以访问外部变量的
具体原理是:我们知道block是一个数据类型
变量 | 显示 | 存储空间 | 生命周期 | 特点 |
成员变量(实例变量、属性、成员属性) | 在类的声明中定义在@interface @end之间或者@property包含的 | 堆区 | 1.定义的时候不能初始化2.只能通过对象访问,不能离开类单独存在 | |
局部变量 | 函数体内或代码块中 | 栈区 | 函数体内 | |
全局变量 | 函数外部 | 静态区 | 整个文件 | 程序一启动就会自动分配内存空间,直到程序释放才结束 |
看下图:问题:如果我要打印num的值,结果是什么?答案是距离NSLog最近的定义的值,就是300,如果把300注释掉会依次往上打印结果
这里注意一下就是block内部可以访问block外部的值,也可以改变block外部的全局变量的值但不可以改变block外部局部变量的值
特别要记住的就是:当block内部访问外部局部变量的时候是把存储在栈区的局部变量以const的形式copy到堆区中,仅仅是值的拷贝,通俗的来说可以理解为浅拷贝
所以我们只能访问到这个值却不能改变这个值.
而剩下的静态全局变量,全局变量,函数参数,也是可以在直接在Block中改变变量值的,但是他们并没有变成Block结构体__main_block_impl_0的成员变量,因为他们的作用域大,所以可以直接更改他们的值。
值得注意的是,静态全局变量,全局变量,函数参数他们并不会被Block持有,也就是说不会增加retainCount值。
2)给局部变量加上__block关键字,则这个局部变量可以在block内部进行修改。
带__block的自动变量 和 静态变量 就是直接地址访问。所以在Block里面可以直接改变变量的值。
注意:
一、静态变量 和 全局变量 在加和不加 __block 都会直接引用变量地址。也就意味着 可以修改变量的 值。在没有加__block 参数的情况下。
二, 常量变量(NSString *a = @"hello";a 为变量,@“hello”为常量。)-----不加__block类型 block 会引用常量的地址(浅拷贝)。加__block类型 block会去引用常量变量(如:a变量,a = @"abc".可以任意修改a 指向的内容。)的地址。
如果不加__block 直接在block 内部修改变量 ,会编译报错。block 内部改变量是 只读的。
7.block作为函数返回值
/* 函数的返回值,一般只能返回值1个值 想返回多个值,必须使用 指针完成 int sum(int a,int b){ return a+b; } //如何实现返回值是一个代码块类型 //定义别名 typedef void (^BlockType)(); BlockType test(){ void (^b1)() = ^{ int a = 10; int s = a+100; NSLog(@"s = %d",s); } //b1(); reurn b1; } //接收 BlockType bb = test(); //bb是一个BlockType类型的,也是无参无返回值的block变量 bb(); */ #import <Foundation/Foundation.h> //定义一个别名 BlockType typedef void (^BlockType)(); typedef void (^BlockType1)(int a,int b); typedef int (^BlockType2)(int a,int b); //定义返回值是BlockType类型的函数 BlockType test(){ //定义block变量 b1 void (^b1)() = ^{ int a = 10; int s = a+100; NSLog(@"s = %d",s); }; //b1(); return b1; } //定义返回值是BlockType1的函数 BlockType1 test1(){ return ^(int a,int b){ NSLog(@"a+b = %d",a+b); }; } BlockType2 test2(){ //return 函数返回值 return ^(int a,int b){ //return block代码块的返回值 return a+b; }; } int main(int argc, const char * argv[]) { @autoreleasepool { //定义BlockType 类型的变量,接收test函数返回的结果i BlockType bb = test(); bb(); //执行 block BlockType1 b2 = test1(); b2(34,10); BlockType2 b3 = test2(); //b3接收了函数的返回值 //因为函数的返回值是一个有参数,有返回值的block //所以,b3可以直接执行block,同时block返回值是int类型 //故,s = b3(10,38); int s = b3(10,38); NSLog(@"s = %d",s); } return 0; }
8.三种类型的block
根据Block在内存中的位置分为三种类型NSGlobalBlock,NSStackBlock, NSMallocBlock。
NSGlobalBlock:类似函数,位于代码段;
NSStackBlock:位于栈内存,函数返回后Block将无效;
NSMallocBlock:位于堆内存
1)全局block定义:定义在函数外部的block或者定义在函数内部但没有捕获任何自动变量(局部变量)成为全局block(ARC和MRC均适用)
2)栈block
栈block定义:在MRC下,block内部使用了自动变量
3)堆block
在ARC下访问自动变量
8.1注意事项一:
block类型变量内存管理参数为什么要使用copy ?
如果block类型变量用assign修饰那么无论在ARC还是MRC环境下block都是栈block,也就意味着block定义的变量存放在栈区,给我们的影响就是block变量会提前被释放,导致无法继续访问.如下图所示:
ARC下:
MRC下:
以上是关于OC加强之ARC的主要内容,如果未能解决你的问题,请参考以下文章