iOS 强弱引用

来源:互联网 发布:詹姆斯个人数据统计 编辑:程序博客网 时间:2024/05/19 15:39

QF——关于iOS的强引用,弱引用及strong,retain,copy,weak,assignd的关系

强引用和弱引用:

我们已经知道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)。 

深拷贝(mutableCopy)和浅拷贝(copy):

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

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

在Objective-C的ARC模式中, 

?
1
id obj1 = [[NSObject alloc] init];
这里虽然没有显示的声明为__strong,但是Objective-C默认声明的一个对象就为__strong,即: 
?
1
id obj1 = [[NSObject alloc] init];
和 
?
1
id __strong obj1 = [[NSObject alloc] init];

是等价的。

在强引用中,有时会出现循环引用的情况,这时就需要弱引用来帮忙(__weak)。 

强引用持有对象,弱引用不持有对象。 

强引用可以释放对象,但弱引用不可以,因为弱引用不持有对象,当弱引用指向一个强引用所持有的对象时,当强引用将对象释放掉后,弱引用会自动的被赋值为nil,即弱引用会自动的指向nil。 

下面用代码来说明: 

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
//
//  main.m
//  ARC中的强引用和弱引用
//
//  Created by on 15/3/31.
//  Copyright (c) 2015年 apple. All rights reserved.
//
 
#import <Foundation/Foundation.h>
 
intmain(intargc, constchar * argv[]) {
    @autoreleasepool {
        id __weak obj0 = nil;
        if(YES) {
            id obj1 = [[NSObject alloc] init];
            obj0 = obj1;
            NSLog(@"obj0: %@", obj0);
        }
        NSLog(@"obj0: %@", obj0);
    }
    return0;
}
 
/*
 *  输出结果
 *  obj0: <NSObject: 0x1003066c0>
 *  obj0: (null)
 *
 *  因为obj1生成的默认的为强引用(__strong),在超出if的作用域之后,obj1所持有的对象被释放,
 *  obj0为弱引用,所以obj0不持有对象,在obj1对象释放后,obj0自动的被赋值为nil
 *  弱引用的特性是,不持有对象,即便是写成id __weak obj1 = [[NSObject alloc] init];
 *  此代码系统会给与警告,因为这里obj1被声明成弱引用,那么在赋值之后,alloc出来的对象会被立即释放。

0 0
原创粉丝点击