这是我参与「第四届青训营 -iOS场」笔记创造活动的的第2篇笔记
内存管理
堆和栈
栈
- 栈,stack,存储push,销毁pop;寄存器中保存stack pointer,指向栈顶
- 存储参数、局部变量、函数调用后回来地址,线程安全
- 由高地址向低地址扩展
堆
- swift,由双向链表组成
- 存储数组和目标,线程共享
- 手动分配,低地址向高地址扩展
引证计数
- 记录当前内存资源有多少指针在引证
- 新增加一个能够拜访这个资源的引证,计数器就会+1,反之就会-1;到0的时分就能够被收回
MRC
- 需求手动进行引证计数的管理
- alloc/new/copy/mutableCopy,创立的办法,引证计数=1
- retain 引证计数+1
- release 引证计数-1,到0时,会进行内存收回
Autorelease-Pool
- 把目标放入到自动开释池,会进行延迟统一开释
- 减少内存的峰值
ARC
- 编译器自动参加内存管理代码,不需求手动维护引证计数
- 只需有一个强指针指向内存目标,目标就不能被开释,ARC销毁的时间为强引证的个数为0,若指针需求显现声明
循环引证
- 最常出现的是署理形式,A类引证B类,A类的署理指向C类,C中的特点再指向A
润饰符
- strong,强引证
- weak,弱引证
- copy,在setter中经过深仿制进行设置目标,调用了copy的办法
代码顶用copy润饰不可变目标,确保自己拥有的是一份新的地址空间的值,确保不被外界修正,内存安全
- assign,指定setter进行简单赋值,用于根本类型。NSInteger/CGRect,默许润饰符
深浅仿制
- 浅仿制,指针仿制,仿制一个新的指针,仿制后指向同一块内存区域
- 深仿制,内容仿制,内存中的目标仿制了一份,放在一块新的区域,仿制后指向的是不同的区域
NSString和NSMutableString
- NSString调用copy后,发生的是浅仿制,指向的是同一个地址;调用mutableCopy,发生的是深仿制,指向的不同的地址,创立的是新的NSMutableString目标,再赋值给NSString
- NSMutableString调用copy和mutableCopy,发生的都是深仿制,指向的是不同的地址
- 关于NString,润饰符无论是strong仍是copy,发生的都是浅仿制,由于是不可变的,因此浅仿制也没事
- 关于NSMutableString,copy润饰后,发生深仿制;strong发生的是浅仿制,由于是直接赋值
内存引起的crash
- 野指针,当所指向的目标被提前开释或者收回,可是该指针没有任何修正,以至于该指针仍指向已经被修正或收回的内存区域
- OOM,某个应用由于内存占用过高,而被操作系统强制停止
block
- 能够分配在栈和对上,也能够是大局的,分配在栈上的块,能够仿制到堆上,具有引证计数
- 本质上是一个OC目标
运用
- 声明,能够用
typedef
定一个block类型,便利实用
// 回来值 (^blockname)(参数);
void (^voidBlockType)(void);
NSInteger (^compute)(NSInteger a, NSInteger b);
- 放入函数中
+ (NSInteger) blockTest1: (voidBlockType)myBlock :(compute)mycompute;
+ (NSInteger) blockTest2: (NSInteger (^)(NSInteger a, NSInteger b))compute;
- 函数调用
+ (NSInteger) blockTest1: (voidBlockType)myBlock :(compute)mycompute {
myBlock();
return mycompute(10, 20);
}
// 作为函数参数
+ (NSInteger) blockTest2: (NSInteger (^)(NSInteger a, NSInteger b))compute {
return compute(10, 20);
}
内存
- 依据存储办法位置分为三种
- 大局
__NSGlobalBlock
- 栈
__NSStackBlock
- 堆
__NSMallocBlock
- ARC形式下,会默许调用block的copy办法,仿制到堆区,确保运用安全
- block作为函数回来值
- 将block仿制给strong指针
- 作为系统办法参数
- 在MRC下,要用copy润饰block特点
变量捕获
- block默许是值引证,再生成block时,会仿制一份block捕获的变量,其中会脱离上下文运用
无论是OC目标仍是根本数据类型,都是值仿制
- block中引证
__block
润饰的值,不再捕获变量,而是目标进行名称引证
,随着外部值的改变而改变 - block经过self进行变量引证运用时,捕获的是self的值,会给self发送音讯,获取变量
分类
- 值捕获,仿制对应的值,block中的变量脱离上下文
- 名称引证,盯梢值改变
- 添加__block
- 捕获目标特点
循环引证
- 在block中经过self引证变量,那么就会给self+,此时self也引证block,发生循环引证
- 在block内部进行引证,需求经过
weak self
,可是在运用的时分要用__strong
引证变量,避免在block履行过程中,self被开释
应用
- 数组变量,
enumerate
办法簇 - 传递数据,进行处理回调
- 链式调用,block回来值为
原类目标
// .h
@interface Calculate : NSObject
typedef Calculate* _Nullable (^CalculateBlock)(NSInteger num);
@property (nonatomic) NSInteger result;
- (CalculateBlock)add;
- (CalculateBlock)mul;
@end
// .m
@implementation Calculate
- (CalculateBlock)add {
return ^(NSInteger num) {
self.result += num;
return self;
};
}
- (CalculateBlock)mul {
return ^(NSInteger num) {
self.result *= num;
return self;
};
}
@end
// 调用
Calculate *calculate = [Calculate new];
// 调用add回来的闭包
calculate.add(2).mul(3);
NSLog(@"%ld", calculate.result);
- 异步操作,GCD