iOS 学习日志(4)----ARC rules

ARC工作原理

每次创建一个类的实例,ARC就会分配一个内存块,用来存储这个实例的相关信息。这个内存块保存着实例的类型,以及这个实例相关的属性的值。

当实例不再被使用时,ARC释放这个实例使用的内存,使这块内存可作它用。这保证了类实例不再被使用时,它们不会占用内存空间。

但是,如果ARC释放了仍在使用的实例,那么你就不能再访问这个实例的属性或者调用它的方法。如果你仍然试图访问这个实例,应用极有可能会崩溃。

ARC的一个基本规则:只要某个对象被任一strong指针指向,那么它将不会被销毁。如果对象没有被任何strong指针指向,那么就将被销毁

1、strong关键字:与retain类似,引用计数自动+1。强引用,只要强持有某个实例,并且这个实例的强引用存在,就不能销毁这个实例。默认下是强引用

下面的例子对 strong的使用,有很详细的说明:

id __strong obj0 = [[NSObject alloc] init]; /* object A */
/** obj0 has a strong reference to object A
*/
id __strong obj1 = [[NSObject alloc] init]; /* object B */
/** obj1 has a strong reference to object B
*/
id __strong obj2 = nil;
/** obj2 has no reference
*/
obj0 = obj1;
/**Obj0 has a strong reference to object B, which has been assigned from obj1.
* So, obj0 does not have a strong reference to object A anymore.
* Object A is disposed of because no one has ownership of it.** At this moment, both obj0 and obj1 have strong references to object B.
*/
obj2 = obj0;
/** Through obj0, obj2 has a strong reference to object B.** At this moment, obj0, obj1 and obj2 have strong references to object B.
*/
obj1 = nil;
/** Because nil is assigned to obj1, strong references to object B disappear.
** At this moment, obj0 and obj2 have strong references to object B.*/
obj0 = nil;
/** Because nil is assigned to obj0, a strong reference to object B disappears.
** At this moment, obj2 has a strong reference to object B.*/
obj2 = nil;
/** Because nil is assigned to obj2, a strong reference to object B disappears.
* Object B is disposed of because no one has ownership of it*/

  1. id obj = [array objectAtIndex:0]; 
    [array removeObjectAtIndex:0]; 
    NSLog(@"%@",obj);

在MRC时代这几行代码应该就挂掉了,因为array中0号对象被remove以后就被立即销毁了,因此obj指向了一个dealloced的对象,因此在NSLog的时候将出现EXC_BAD_ACCESS。而在ARC中由于obj是strong的,因此它持有了array中的首个对象,array不再是该对象的唯一持有者。即使我们从array中将obj移除了,它也依然被别的指针持有,因此不会被销毁。

2、weak关键字:与assign类似,但更聪明。弱引用类型的指针也可以指向对象,但是并不会持有该对象。对象一旦被释放,这些指向这个对象的weak指针都将被赋值为nil。这样的好处能有效的防止野指针。例如:

  1. __weak NSString *str = [[NSString alloc] initWithFormat:…]; 
    NSLog(@"%@",str); //输出是"(null)"

这两句代码没有任何意义。由于str是弱引用,不会持有alloc出来的对象。根据ARC的规则,一个对象没有强引用,这个对象就会被释放。

3、unsafe_unretained:顾名思义,不安全;与weak有点类似。指针也是可以指向对象,但是并不会持有该对象。对象一旦被释放,这些指向这个对象的unsafe_unretained指针并不会知道对象已被释放,造成了野指针的出现,程序会crash。尽量少用unsafe_unretained关键字,使用了必须手动去管理实例。例如:下面的代码会崩溃

@property (nonatomic, strong) NSString *string1;  
@property (nonatomic, unsafe_unretained) NSString *string2; 

self.string1 = [[NSString alloc] initWithUTF8String:"string 1"];     
self.string2 = self.string1;     
self.string1 = nil;    
NSLog(@"String 2 = %@", self.string2);

4、__autoreleasing:可以使对像延迟释放。比如你想传一个未初始化地对像引用到一个方法当中,在此方法中实始化此对像,那么这种情况将是__autoreleasing表演的时候

注:弱引用只能声明为变量类型,因为运行时它的值可能改变。弱引用绝对不能声明为常量

5、循环引用:一个类的实例一直都有强引用以致实例无法释放;(1)在两个类实例彼此保持对方的强引用,使得每个实例都使对方保持有效时会发生这种情况。我们称之为循环引用。

id test0 = [[Test alloc] init];
id test1 = [[Test alloc] init];
[test0 setObject:test1];
[test1 setObject:test0];


172003_oJaI_1040495.png

(2)类的实例自己引用自己的实例。

id test = [[Test alloc] init];
[test setObject:test];

172255_HMl9_1040495.png

附录:

EXC_BAD_ACCESS:这种情况是对指针对象的过度释放,导致次指针为野指针报错。这类的报错有时候是很难找出报错的位置的。从网上资料找出2种调试方法:

<1>通过NSZombieEnabled (这方法经常使用,但少数的还是无法查找出来)

在xcode中Run,Stop 右边也就是选择设备的地方左边找到 

 Scheme >Edit Scheme>Arguments>Environment Variables下添加

NSZombieEnabled               YES    

MallocStackLoggingNoCompact  YES

 MallocStackLogging                      YES

<2>通过重写object的respondsToSelector方法,显示出EXC_BAD_ACCESS前访问的最后一个对象

你需要在每个object的.m或者.mm文件中加入上面代码,并且在 other c flags中加入-D _FOR_DEBUG_(记住请只在Debug Configuration下加入此标记)。这样当你程序崩溃时,Xcode的console上就会准确地记录了最后运行的object的方法。

 #ifdef _FOR_DEBUG_  
-(BOOL) respondsToSelector:(SEL)aSelector {  
    printf("SELECTOR: %s\n", [NSStringFromSelector(aSelector) UTF8String]);  
    return [super respondsToSelector:aSelector];  
}  
#endif


转载于:https://my.oschina.net/u/1040495/blog/306908

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值