iOS下的内存管理

来源:互联网 发布:win8网络受限 编辑:程序博客网 时间:2024/05/29 11:15
     最近由于工作原因好久没有更新微博了,今天就简单谈谈iOS最常见的内存管理问题,由于iOS现在一般都是ARC模式,也就是自动引用计数来管理内存,管理起来比较简洁,ARC是编译器(时)特性,而不是运行时的特性,但是要深刻理解并不是一件易事,内存管理仍是一个重点关注的问题,如果只是盲目开发而不知其中的原理,踩到坑里就很难跳出来了,理解好内存管理,能让我们写出更有质量的代码。
     如果程序运行时一直分配内存而不及时释放无用的内存,会造成这样的后果:程序占用的内存越来越大,直至内存消耗殆尽,程序印务内存可用导致崩溃,这样的情况我们称之为内存泄漏。

1.内存消耗
内存消耗这是应用消耗的RAM,应用中的内存消耗分为两部分,栈大小和对大小。
栈:应用中新创建的每个县城都有专用的占空间,栈可以在线程存在期间自由使用,栈可以在线程存在期间自由使用。
堆:每个进程的所有线程共享一个堆。一个应用可以使用的堆大小通常远远小于设备的RAM值。例如,iPhone5s拥有大约1GB的RAM,但是分配给一个应用的堆大小最多不到512MB。应用并不能控制分配给他的堆,只有操作系统才能管理堆。


1.引用计数
OC中什么时候对象会被释放?
当对象没有被任何变量引用(没有指针指向该对象)的时候就会被释放。
怎么知道对象已经没有被引用了呢?
OC中采用引用计数来进行管理
1)每个对象都有一个关联的整数,称为引用计数器
2)当代码需要使用该对象时,则将对象的引用计数加1
3)当代码结束使用该对象时,则将对象的引用计数减1
4)当引用计数的值变为0时,表示对象没有被任何代码使用,此时对象将被释放。
与之对应的消息发送方法如下:
1)当对象被创建(通过alloc、new或copy等方法)时,其引用计数初始值为1
2)給对象发送retain消息,其引用计数加1
3)給对象发送release消息,其引用计数减1
4)当对象引用计数归0时,ObjC給对象发送dealloc消息销毁对象

要定义一个weak型的NSString引用,它的写法应该是:
NSString * __weak str = @"hehe";// 正确!
而不应该是:
__weak NSString *str = @"hehe"// 错误!

1.1自动引用计数
strong:
相当于老版本的retain,而且可以不再需要做release操作了,只要有强变量的引用,对象就不会释放内存。
weak:
相当于老版本的assign。但是只适应于对象,当弱变量引用的对象被别的变量释放,那么弱变量会被自动设置为nil,这样可以有效地防止崩溃
strong 和 copy的区别
@interfaceViewController ()
@property (nonatomic,strong)NSString *text;
@property (nonatomic,copy)NSString *textTwo;
@end

@implementation ViewController

- (void)viewDidLoad {
    [superviewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    self.view.backgroundColor = [UIColorwhiteColor];
    //有效的证明了copystrong的区别
    NSMutableString *m = [NSMutableStringstringWithString:@"Strawberry"];
    self.text = m;
    self.textTwo = m;
    // at this point, _text is @"Strawberry"
    [m appendString:@" and banana"];
    NSLog(@"&m == %p",&m);
    NSLog(@"&_text == %p",&_text);
    NSLog(@"&_textTwo == %p",&_textTwo);
    NSLog(@"self.text == %@",self.text);
    NSLog(@"self.textTwo == %@",self.textTwo);
}
输出:
2017-06-20 16:15:09.339 MemoryManageDemo[9094:234421] &m == 0x7fff50dc99e8
2017-06-20 16:15:09.340 MemoryManageDemo[9094:234421] &_text == 0x7fefa0c06a38
2017-06-20 16:15:09.340 MemoryManageDemo[9094:234421] &_textTwo == 0x7fefa0c06a40
2017-06-20 16:15:09.340 MemoryManageDemo[9094:234421] self.text == Strawberry and banana
2017-06-20 16:15:09.340 MemoryManageDemo[9094:234421] self.textTwo == Strawberry

因为执行self.text = m时,实际上是把指针指向了m所指向的对象,所以m和someObject.text指针指向同一个对象。
而self.textTwo则是先将m中的对象copy了一份,然后再指向这个copy,所以并不会因为m变化而变化。
注意上文说的copy特性,是建立一个索引为1的对象。

总结一下:
1.对基础数据类型 (例如NSInteger,CGFloat)和C数据类型(int, float, double, char, 等)适合用assign特性
2.对于NS开头,UI开头的对象引用 比如(NSMutableArray *,NSMutableDictionary * ,NSMutableString *,UIImage *, UIColor *等)可以用strong特性
3.对于NSArray、NSDictionary、NSString最好用copy类型。
4.对UI控件的引用,iOS会自动将其设置为弱变量(weak)

2.__block和__weak的区别和联系?
1.__block不管是ARC还是MRC模式下都可以使用,可以修饰对象,还可以修饰基本数据类型。 
2.__weak只能在ARC模式下使用,也只能修饰对象(NSString),不能修饰基本数据类型(int)。 
3.__block对象可以在block中被重新赋值,__weak不可以。 
4.__block对象在ARC下可能会导致循环引用,非ARC下会避免循环引用,__weak只在ARC下使用,可以避免循环引用。
帮助理解:
strong型指针就像是栓住的狗。只要你用牵绳挂住狗,狗就不会跑掉。如果有5个人牵着一条狗(5个strong型指针指向1个对象),除非5个牵绳都脱落 ,否着狗是不会跑掉的。
weak型指针就像是一个小孩指着狗喊到:“看!一只狗在那” 只要狗一直被栓着,小孩就能看到狗,(weak指针)会一直指向它。只要狗的牵绳脱落,狗就会跑掉,不管有多少小孩在看着它。
只要最后一个strong型指针不再指向对象,那么对象就会被释放,同时所有的weak型指针都将会被清除。
原创粉丝点击