IOS 高级内存管理 ARC (Automatic Reference Counting) 原理分析

限于喜欢 提交于 2019-12-16 22:00:05

ARC rules

1.你不能够清晰的调用dealloc,implement或者invoke retain, release, autorelease,同时也不能够
使用衍生品,比如@selector(retain),@selector(release)
但是你可以implement dealloc,但是在写的这个dealloc中间不能够release instance variable,也不能够调用
[super dealloc],这些系统都帮你办了,但是你可能需要写[classInstance setDelegate:nil]这样的不能由ARC
覆盖的内容。你依然可以使用CFRetain, CFRelease
2.你不能使用NSAllocateObject和NSDeallocateObject,你可以使用alloc来创建物体,但是系统会自动dealloc
3.你不能在C struct中间使用object的指针,你可以使用objective c的class来做同样的事情
4.不能够在id和void*之间随意转换
5.不能使用NSAutoReleasePool Object,取代它的是@autoreleasepool block,后者效率更高
6.不能使用NSZone
7.命名的时候access不能以new打头,也就是说不能定义
@property NSString* newTitle

 

ARC new lifetime qualifier
引入了strong和weak

// 使用strong替代了 @property(retain) MyClass *myObject;
@property(strong) MyClass *myObject;

//使用weak替代了 "@property(assign) MyClass *myObject;"
//差别在于如果引用的这个Myclass被dealloc的话,那么myObject会
//被自动设置成nil,而assign的话,那么就会出现一个野指针
@property(weak) MyClass *myObject;

默认的property模式是strong

 

对于没有使用property的变量定义类型
_strong
_weak
_unsafe_unretained
_autoreleasing

默认是_strong,以下例子是一样的意思

NSString* str=[[NSString alloc] init];
NSString* _strong str=[[NSString alloc] init];

其实本质上所有的alloc, init后面都被加上了autorelease

UIColor* color=[[UIColor alloc] init];

会被系统自动写成

UIColor* color=[[[UIColor alloc] init] autorelease];

所以使用weak的变量hold不住这个值,比如以下的UIColor其值是nil

UIColor* __weak color=[[UIColor alloc] init];

 

特别要注意的例子

NSString * __weak string = [[NSString alloc] initWithFormat:@"First Name: %@", [self firstName]];
NSLog(@"string: %@", string);

这里的NSLog出来的是nil

但是对于以下两个例子NSLog却是有值的

NSString* __weak str=[[NSString alloc] initWithString:@"FirstName"];
NSString* __weak str=@"FirstName";

对于_weak来说就是不retain,这种时候,如果string的内容也就是alloc的量被release了,那么不会保留一个野(即指向不明的内存快)指针,而是被set成nil,如果想要保留一个野指针,那么使用_unsafe_unretained

对于堆栈上的变量_weak, _strong, _autoreleasing都会被默认为nil

- (void)myMethod {
NSString *name;
NSLog(@"name: %@", name);
}

这里的NSLog就会出现一个nil


With ARC, instance variables are strong references by default—assigning an object to an instance variable directly does extend the lifetime of the object.
使用时的例子,以下例子效果相同,一个使用property (weak),一个使用_weak

例子1

@interface MyClass : Superclass {
id __weak thing;
}
// ...
@end
@implementation MyClass
- (id)thing {
return thing;
}
- (void)setThing:(id)newThing {
thing = newThing;
}
// ...
@end

 

例子2

@interface MyClass : Superclass
@property (weak) id thing;
// ...
@end
@implementation MyClass
@synthesize thing;
// ...
@end

 


How do I think about ARC? Where does it put the retains/releases?
Try to stop thinking about where the retain/release calls are put and think about your application algorithms instead. Think about “strong and weak” pointers in your objects, about object ownership, and about possible retain cycles.
文档明确指出strong和weak已经可以cover所有的情况了。

In particular, the common “return a retain/autoreleased object” pattern is much faster and does not actually put the object into the autorelease pool, when the caller of the method is ARC code.
和我猜测的一样,autoRelease实际上在下一次的赋值的时候就进行了运算,即release的操作,这样如果count为0则dealloc,可以参见前面的那个_weak的例子,其中返回的一个NSString的值,赋值给一个_weak的时候,就被release掉了,所以log出来是NULL

Which classes don’t support weak references?
You cannot currently create weak references to instances of the following classes:
NSATSTypesetter, NSColorSpace, NSFont, NSMenuView, NSParagraphStyle, NSSimpleHorizontalTypesetter, and NSTextView.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!