ARC

ARC

1、ARCAutomatic Reference Counting(自动引用计数器)的简称。

ARC是ios5.0引入的新特性,完全消除手动管理内存的繁琐,编译器会自动在适合的代码里面插入适当的retain,release,autorelease的语句。我们不要再担心内存管理,因为编译器帮我们做了这一切。
ARC是编译器的特性,并非运行时的特性

2、基本原理

ARC的规则就是只要对象没有强指针引用,就会被释放掉,换而言之 只要还有一个强引用指针变量指向对象,那么这个对象就会存在内存中。弱指针指向的对象,会被自动变成空指针(nil指针),从而不会引发野指针错误。

AutoreleasePool

参考:
https://www.jianshu.com/p/b75a99892261

自动释放池存储于内存中的栈并遵循"先进后出"原则,因为它是将数据存储在栈的容器中。因此就出现先进后出原则

1、介绍

autoReleasePool和ARC都是iOS5.0出来的,AutoreleasePool(自动释放池)是OC中的内存自动回收机制,它可以延迟自动释放池中变量release的时机。在正常情况下,创建的变量会在超出其作用域的时候release,但是如果将变量加入AutoreleasePool,那么release将延迟执行。

2、ARC下使用场景

苹果官方给的建议之一是 循环中包含了大量临时创建的对象。
除此之外,当函数写的很长,在中间出现很多变量,占据大量内存也可以使用

ARC下用 @autoreleasepool {}主要还是为了避免内存峰值。
正常情况下,你创建的变量会在超出其作用域的时候被释放掉。
而如果你的函数写的很长,在你函数运行过程中出现很多中间变量,占据了大量的内存,怎么办?
用@autoreleasepool。在@autoreleasepool中创建的变量,会在@autoreleasepool结束的时候执行一次release,进行释放。其实@autoreleasepool就相当于一层作用域。

3、autorelease的优化

1)优化内存,在for循环创建的时候,使用@autoreleasepool 包起来,让每次循环结束时,可以及时释放临时对象的内存

4、解释

@autoReleasePool什么时间释放? 每次Runloop结束时会有专门的时机用来释放

5、用法

@autoreleasepool {
// code do something, creates some autoreleases objects
}

6、autorelease使用注意:

1.占用内存大的对象不要随便使用autorelease,担心对象释放的时间太迟

2.占用内存小的对象使用autorelease,没有太大影响
autoreleasepool:在iOS程序运行时,会创建无数个池子,这些池子以栈结构存在(先进后出);当一个对象调用autorelease方法时,会将这个对象放到栈顶的释放池。

7.堆和栈的区别:

.text段 : 存放代码

.data区 : 存放全局变量

堆区 : 存放对象,需要程序员手动释放

栈区 : 存放局部变量 ,程序自动管理内存

8.引用计数器

  • 用来表示对象被引用的次数,当为0时,会被回收,新对象被创建时,默认为1
  • retain +1, release -1, retainCount查看
  • 当对象的的引用计数器为0时,它将被销毁,系统会向对象发送一条dealloc消息,dealloc就像对象的遗言,要重写dealloc方法,并且在调用[super dealloc]方法时,一定要放在最后
    当使用new alloc copy等关键字时,引用计数器会+1
    使用release或者autorelease时会-1

9.常见错误

1.僵尸对象:引用计数器为0的对象为僵尸对象

2.野指针:指向僵尸对象的指针 继续释放会崩溃 EXC_BAD_ACCESS(code=1,address=)

3.空指针:没有指向任何东西的指针

4.防止野指针出现常用方法:p=nil

10.循环引用问题的出现:相互retain

解决思路:
1、一段使用retain,另一端使用assign

2、使用assign段中,在dealloc方法中不需要释放对方

11.ARC

1.不允许调用release、retain、retainCount

2.允许重写dealloc,但是不允许调用[super dealloc]

12.ARCMRC混用

1.自己的旧项目没有使用ARC,但是引入的第三方库却是使用了ARC的。
(给采用了ARC的源文件,添加-fobjc-arc选项)

2.自己的新项目使用了ARC,但是引入的第三方库或者以前写的代码却没有使用ARC。
(添加-fno-objc-arc) build Phases找到相应的类,添加-fno-objc-arc

13.使用block时什么情况会发生引用循环,如何解决?

一个对象中强引用了block,在block中又使用了该对象,就会发生循环引用。
解决方法是将该对象使用__weak或者__block修饰符修饰之后再在block中使用
__weak __typeof(&*self)weakSelf = self 调用外部方法
id __block weakSelf = self; 在block内部修改外部变量的值

 #define WS(weakSelf)  __weak __typeof(&*self)weakSelf = self;
 
 WS(weakSelf)
 [self.tableView addHeaderWithCallback:^{
    [weakself requestMemberList];
 }];

14.Objective-C如何对内存管理的,说说你的看法和解决方法?

  1. 每个对象都有一个引用计数器,每个新对象的计数器是1,当对象的计数器减为0时,就会被销毁
    2.通过retain可以让对象的计数器+1、release可以让对象的计数器-1
    3.还可以通过autorelease pool管理内存

4.如果用ARC,编译器会自动生成管理内存的代码
注意:不管是MRC还是ARC都是在编译时完成的

15.内存管理的几条原则时什么?按照默认法则.哪些方法生成的对象需要手动释放?在和property结合的时候怎样有效的避免内存泄露?

1.只要调用了alloc、copy、new方法产生了一个新对象,都必须在最后调用一次release或者autorelease
2.只要调用了retain,都必须在最后调用一次release或者autorelease
3.@property如果用了copy或者retian,就需要对不再使用的属性做一次release操作
4.如果用了ARC,另外讨论

16.看下面的程序,三次NSLog会输出什么?为什么?

    NSMutableArray* ary = [[NSMutableArray array] retain];
    NSString *str = [NSString stringWithFormat:@"test"];
    [str retain];
    [ary addObject:str];
    NSLog(@"%ld", (unsigned long)[str retainCount]);
    [str retain];
    [str release];
    [str release];
    NSLog(@"%ld", (unsigned long)[str retainCount]);
    [ary removeAllObjects];
    NSLog(@"%ld", (unsigned long)[str retainCount]);
结果:-1、-1、-1 。-1代表没有引用计数或者引用计数非常大,因为str是字符串,字符串在常量区,没有引用计数。引用计数为-1,这可以理解为NSString实际上是一个字符串常量,是没有引用计数的(或者它的引用计数是一个很大的值(使用%lu可以打印查看),对它做引用计数操作没实质上的影响)

17.写一个setter方法用于完成@property (nonatomic,retain)NSString *name,写一个setter方法用于完成@property(nonatomic,copy)NSString *name.
@property (nonatomic, retain) NSString *name;

- (void)setName:(NSString *)name
{
  if (_name != name) {
    [_name release];
    _name = [name retain];
  }
}
2>  @property(nonatomic, copy) NSString *name;
- (void)setName:(NSString *)name
{
  if (_name != name) {
    [_name release];
    _name = [name copy];
  }
}

18.Objective-C使用什么机制管理对象内存?

MRC 手动引用计数
ARC 自动引用计数,现在通常 ARC
通过 retainCount 的机制来决定对象是否需要释放。 每次 runloop 的时候,都会检查对象的 retainCount,如果 retainCount 为 0,说明该对象没有地方需要继续使用了,可以释放掉了

19.ARC下还会存在内存泄露吗?

循环引用会导致内存泄露.
Objective-C 对象与 CoreFoundation 对象进行桥接的时候如果管理不当也会造成内存泄露.
CoreFoundation 中的对象不受 ARC 管理,需要开发者手动释放

20>Objective-C 如何对内存管理的,说说你的看法和解决方法?

答:Objective-C的内存管理主要有三种方式ARC(自动内存计数)、手动内存计数、内存池。
1). 自动内存计数ARC:由Xcode自动在App编译阶段,在代码中添加内存管理代码。
2). 手动内存计数MRC:遵循内存谁申请、谁释放;谁添加,谁释放的原则。
3). 内存释放池Release Pool:把需要释放的内存统一放在一个池子中,当池子被抽干后(drain),池子中所有的内存空间也被自动释放掉。内存池的释放操作分为自动和手动。自动释放受runloop机制影响。

你可能感兴趣的:(ARC)