这是我参与「第四届青训营 -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);
}

内存

  • 依据存储办法位置分为三种
  1. 大局 __NSGlobalBlock
  2. __NSStackBlock
  3. __NSMallocBlock
  • ARC形式下,会默许调用block的copy办法,仿制到堆区,确保运用安全
  1. block作为函数回来值
  2. 将block仿制给strong指针
  3. 作为系统办法参数
  4. 在MRC下,要用copy润饰block特点

变量捕获

  • block默许是值引证,再生成block时,会仿制一份block捕获的变量,其中会脱离上下文运用

无论是OC目标仍是根本数据类型,都是值仿制

  • block中引证__block润饰的值,不再捕获变量,而是目标进行名称引证,随着外部值的改变而改变
  • block经过self进行变量引证运用时,捕获的是self的值,会给self发送音讯,获取变量

分类

  • 值捕获,仿制对应的值,block中的变量脱离上下文
  • 名称引证,盯梢值改变
  1. 添加__block
  2. 捕获目标特点

循环引证

  • 在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