美文网首页
ios内存管理

ios内存管理

作者: 一个好笑的人 | 来源:发表于2021-09-18 01:09 被阅读0次

速查备忘

OC基础之类别(Category)和扩展(Extension): https://www.jianshu.com/p/dc3196030a03
分类(category)和类扩展(extension)_西瓜的博客-CSDN博客

property关键字详解 :https://www.jianshu.com/p/d8f2d170f809

键值编程:https://www.jianshu.com/p/38fdad9689d2

Property

strong 强引用,引用计数+1,相当于MRC里的retain

weak 弱引用,不持有对象,不增加引用计数,在对象销毁后会自动置nil。(必须用于oc对象)

assign 弱引用 (赋值特性) ; setter方法将传入参数赋值给实例变量;仅设置变量时,assign用于基本数据类型(这个是关键)。

copy 拷贝特性。setter方法将传入对象复制一份,需要完全一份新的变量时。

copy

  • block 使用 copy 是从 MRC 遗留下来的“传统”;

在 MRC 中,方法内部的 block 是在栈区的,使用 copy 可以把它放到堆区;

对于 block 使用 copy 还是 strong 效果是一样的。

  • 使用copy的目的是,防止把可变类型的对象赋值给不可变类型的对象时,可变类型对象的值发送变化会无意间篡改不可变类型对象原来的值。

copy & strong

首先明确:NSString一旦创建后,其长度和内容都不可修改。

如果源字符串是NSMutableString的时候,使用strong只会增加引用计数。

但是copy会执行一次深拷贝,会造成不必要的内存浪费。而如果原字符串是NSString时,strong和copy效果一样,就不会有这个问题。

但是,我们一般声明NSString时,也不希望它改变,所以一般情况下,建议使用copy,这样可以避免NSMutableString带来的错误。

assign & weak(解释了为何assign允许不置空)

我们都知道,assign用来修饰基本数据类型,weak用来修饰OC对象。

其实照理,assign也能修饰OC对象,但是assign修饰的对象在该对象释放后,其指针依然存在,不会被置为nil——这就造成了一个很严重的问题:出现了野指针。当访问这个野指针时,指向了原地址,而原地址

是nil,所以会造成程序的crash。但是用weak来修饰的话,对象释放的时候会把指针置为nil,从而避免了野指针的出现。

那又有个疑问出现了,凭什么基本数据类型就可以使用assign。这就要扯到堆和栈的问题了,基本数据类型会被分配到栈空间,而栈空间是由系统自动管理分配和释放的,就不会造成野指针的问题。

ARC

ARC:Automatic Reference Counting ,自动引用计数器。

启用ARC后,编译器会在何时的地方帮我们插入retain/release代码。

ARC -retainable object pointer

  • block指针

  • oc对象指针

  • attribute((NSObject))标记的对象(不常用,暂时没见过)

ARC里创建或得到对象指针的方式有五种:

  • alloc

  • new

  • copy

  • mutable

  • init

ARC的对象修饰符

  • __strong 是默认的。只要有强类型指针指向一个对象,那么该对象会一直”生存“下去。

  • __weak 表明一个不会维持所持对象生命期的引用。当没有强引用指向该对象时,弱引用会设置为nil。

  • __unsafe_unretained 指定一个引用,该引用不会维持所持对象的生命期,并且在没有强引用指向对象时也不会设置为nil。如果它所指向的对象已经被释放,那么它会成为一个野指针。

  • __autoreleasing 用以指示以引用(id*)传入的参数并在return后自动释放。

//ARC strong 
{
  id __strong obj =[[NSObect alloc] init];//启用了ARC,obj在出了作用域之后会自动释放。
  id obj_1=[[NSObect alloc] init];//__strong是缺省值,可以不写。该句和上一句等价
}
//ARC weak
{
  id __weak obj=[[NSObect alloc] init];//obj执行到下一句就会被置nil,因为没有强引用指向被创建到对象,该对象随即就会被销毁!
  ..
  ..
  ..      
}

Retain Cycle

  • property - weak

  • block - weak,@weakify&@strongify

关于block的retain cycle问题

block什么情况下会出现retain cycle

@property(nonatomic,copy) void(^myBlock)(void);//由于self已经强持有block了

-(void)func{
  self.myBlock=^{
    [self doSomething]//而在这里block又强持有self,于是出现循环引用。
  }
}
-(void)doSomething
{
}

方法1:解决block的retain cycle

在@weakify&@strongify出现之前用这种方式处理

@property(nonatomic,copy) void(^myBlock)(void);//self强持有block

-(void)func{
  __weak typeof(self) weakSelf=self;//这里使用ARC里的对象修饰符__weak,新建一个弱引用指向self
  self.myBlock=^{
    __strong __typeof__(self) self_strong_ = self_weak_;//这里加一层强引用是为了保证block里面的代码未执行完的时候self不会突然被释放
    [self_strong_ doSomething]//引用链中有一层weak所以不会造成retain cycle
  }
}
-(void)doSomething
{
}

方法2:解决block的retain cycle

@weakify&@strongify本质是个宏,把方法一的解决方案用宏书写简化了

@property(nonatomic,copy) void(^myBlock)(void);//self强持有block

-(void)func{
  @weakify(self)//定义了一个__weak修饰的self_weak_变量
  self.myBlock=^{
    @strongify(self)//局部定义了一个__strong的self指针指向self_weak
    [self doSomething]//此时的self是局部的,是对真正的self的一个弱引用,可以愉快使用
  }
}
-(void)doSomething
{
}

相关文章

网友评论

      本文标题:ios内存管理

      本文链接:https://www.haomeiwen.com/subject/temmwltx.html