美文网首页基础iOS进阶指南程序员
关于iOS的强引用,弱引用及strong,retain,copy

关于iOS的强引用,弱引用及strong,retain,copy

作者: 若幹年後 | 来源:发表于2016-05-10 10:58 被阅读1311次

    强引用和弱引用:

    我们已经知道OC中的内存管理是通过“引用计数器”来实现的。一个对象的生命周期取决于它是否还被其他对象引用(是否retainCount=0)。但在有些情况下,我们并不希望对象的销毁时间由是否被其他对象引用来决定,而是这个对象本该是什么时候销毁就什么时候被销毁。这时,我们得引入“强引用”和“弱引用”的概念。

    强引用:当前对象被其他对象引用时,会执行retain操作,引用计数器+1。当retainCount=0时,该对象才会被销毁。因为我们要进行对象的内存管理,所以这是默认的引用方式。(默认是强引用)

    弱引用:当前对象的生命周期不被是否由其他对象引用限制,它本该什么时候销毁就什么时候被销毁。即使它的引用没断,但是当它的生存周期到了时就会被销毁。

    在定义属性时,若声明为retain类型的,则就是强引用;若声明为assign类型的,则就是弱引用。后来内存管理都由ARC来完成后,若是强引用,则就声明为strong;若是弱引用,则就声明为weak。

    所以说,retain和strong是一致的(声明为强引用);assign和weak是基本一致的(声明为弱引用)。之所以说它俩是基本一致是因为它俩还是有所不同的,weak严格的说应当叫“归零弱引用”,即当对象被销毁后,会自动的把它的指针置为nil,这样可以防止野指针错误。而assign销毁对象后不会把该对象的指针置nil,对象已经被销毁,但指针还在痴痴的指向它,这就成了野指针,这是比较危险的。

    避免“强引用循环“的僵局:

    默认的引用方式是强引用,但上面说了有时我们还得使用弱引用,那是什么情况呢?

    答案,强引用循环:A对象强引用了B对象,B对象也强引用了A。因为都是强引用,也就是无论是A是B都要在对方的引用断了后才能销毁,但要断了引用,就必须对方对象销毁。就会出现这种僵局,为了避免出现这种情况,就应该有一个对象“示弱”,使其为“弱引用”。

    比较常见的,视图中的父子视图之间的引用:父视图强引用子视图,子视图弱引用父视图。

    总结:由于要进行内存管理的缘故,OC里的引用默认都是强引用,但为了避免出现”强引用循环僵局“,所以有了弱引用(assign)。

    关于copy:参考链接

    retain和strong都是指针拷贝。当有其他对象引用当前对象时,会拷贝一份当前对象的地址,这样它就也指向当前对象了。所以,还是同一个对象,只是retainCount+1;

    而copy则是内容拷贝。是实实在在的拷贝一个新的对象,拷贝了它的内存内容,成为一个新的对象(retainCount=1)。

    深拷贝就是内容拷贝,浅拷贝就是指针拷贝。

    在OC中,若要进行对象的拷贝,则该对象所属的类必须遵守NSCopying和NSMutableCopy协议,并重写copyWithZone:和mutableCopyWithZone:方法。而系统原生类,之所以可以直接进行拷贝是因为它已帮我们自动做了这些事。

    不管是集合类对象,还是非集合类对象,接收到copy和mutableCopy消息时,都遵循以下准则:

    copy返回imutable对象;所以,如果对copy返回值使用mutable对象接口就会crash;

    mutableCopy返回mutable对象;

    1.下面将针对非集合类对象和集合类对象的copy和mutableCopy方法进行具体的阐述

    系统非集合类对象指的是NSString, NSNumber ...之类的对象。下面先看个非集合类immutable对象拷贝的例子

    NSString*string =@"origin";

    NSString*stringCopy = [stringcopy];

    NSMutableString*stringMCopy= [stringmutableCopy];

    NSLog(@"string %p",string);

    NSLog(@"stringCopy %p",stringCopy);

    NSLog(@"stringMCopy %p--------------------------",stringMCopy);

    通过查看内存,可以看到stringCopy和string的地址是一样,进行了指针拷贝;

    而stringMCopy的地址和string不一样,进行了内容拷贝;

    NSMutableString*string = [NSMutableStringstringWithString:@"origin"];

    //copy

    NSString*stringCopy = [stringcopy];

    NSMutableString*mStringCopy = [stringcopy];

    NSMutableString*stringMCopy = [stringmutableCopy];

    //change value

    //[mStringCopy appendString:@"mm"]; //crash

    [stringappendString:@" origion!"];

    [stringMCopyappendString:@"!!"];

    NSLog(@"动态字符串string %p",string);

    NSLog(@"stringCopy %p",stringCopy);

    NSLog(@"mStringCopy %p",mStringCopy);

    NSLog(@"stringMCopy %p",stringMCopy);

    运行以上代码,会在[mStringCopy appendString:@"mm"];行crash,原因就是copy返回的对象是immutable对象。注释这一行后再运行,查看内存,发现string、stringCopy、mStringCopy、stringMCopy四个对象的内存地址都不一样,说明此时都是做内容拷贝。

    在非集合类对象中:对immutable对象进行copy操作,是指针复制,mutableCopy操作时内容复制;

    对mutable对象进行copy和mutableCopy都是内容复制。用代码简单表示如下:

    [immutableObject copy] //浅复制

    [immutableObject mutableCopy] //深复制

    [mutableObject copy] //深复制

    [mutableObject mutableCopy] //深复制

    2.集合对象的copy与mutableCopy

     集合类对象是指NSArray、NSDictionary、NSSet ...之类的对象。下面先看集合类immutable对象使用copy和mutableCopy的一个例子:

    NSArray*array =@[@[@"a",@"b"],@[@"c",@"d"]];

    NSArray*copyArray = [arraycopy];

    NSMutableArray*mCopyArray =[arraymutableCopy];

    NSLog(@"array %p",array);

    NSLog(@"coptArray %p",copyArray);

    NSLog(@"mcoptArray %p", mCopyArray);

    查看内容,可以看到copyArray和array的地址是一样的,而mCopyArray和array的地址是不同的。说明copy操作进行了指针拷贝,mutableCopy进行了内容拷贝。但需要强调的是:此处的内容拷贝,仅仅是拷贝array这个对象,array集合内部的元素仍然是指针拷贝。这和上面的非集合immutable对象的拷贝还是挺相似的,那么mutable对象的拷贝会不会类似呢?我们继续往下,看mutable对象拷贝的例子:

    NSMutableArray*array = [NSMutableArrayarrayWithObjects:[NSMutableStringstringWithString:@"a"],@"b",@"c",nil];

    NSArray*copyArray = [arraycopy];

    NSMutableArray*mCopyArray = [arraymutableCopy];

    NSLog(@"array %p",array);

    NSLog(@"coptArray %p",copyArray);

    NSLog(@"mcoptArray %p", mCopyArray);

    查看内存,如我们所料,copyArray、mCopyArray和array的内存地址都不一样,说明copyArray、mCopyArray都对array进行了内容拷贝。同样,我们可以得出结论:

    在集合类对象中,对immutable对象进行copy,是指针复制,mutableCopy是内容复制;对mutable对象进行copy和mutableCopy都是内容复制。但是:集合对象的内容复制仅限于对象本身,对象元素仍然是指针复制。用代码简单表示如下:

    [immutableObject copy] //浅复制

    [immutableObject mutableCopy] //单层深复制

    [mutableObject copy] //单层深复制

    [mutableObject mutableCopy] //单层深复制

    相关文章

      网友评论

        本文标题:关于iOS的强引用,弱引用及strong,retain,copy

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