内存管理始终遵循的几点:
1、自己生成的对象,自己所持有。
2、非自己生成的对象,自己也能持有。
3、不再需要自己持有的对象时释放。
4、非自己持有的对象,无法释放。
由于id类型和对象类型的所有权修饰符默认是__strong,所以,不需要写上"__strong".
__strong 大家都知道会造成循环引用,导致内存泄露,所以,__strong自己是无法管理好内存的,还需要另外一个修饰符,"__weak"
带有__strong的变量,持有该对象,然而,__weak的变量,却没有持有该对象,有效的避免了循环引用,而且__weak还有另外一个优点就是,_weak不持有该对象,当他拥有的对象被释放的时候,那此时这个若引用也会自动失效,并且被置为nil的状态。
下面用一个例子来说明__strong和__weak的区别:
想象我们的对象是条狗,狗想要跑掉(即被释放)。
__strong型指针就像是拴住了这条狗,只要你用绳牵住这条狗狗就不会被跑掉。如果有5个人牵着这条狗(5个strong型指针指向这同一个对象),除非5个牵着的绳都脱落,否则狗是不会跑掉的。
__weak 型指针就像是一个小孩指着狗喊叫:“看!一条狗在那”只要狗被栓在那里,小孩就能看到狗,(__weak指针)会一直指向它,只要狗的牵绳脱落,狗就会跑掉,不管有多少小孩在看着它。
只要最后一个strong型的指针都没有指向他,那么这个对象就会被释放,同时,所有的weak型的指针都将会被清除。
而__unsafe_unretained是跟__weak类似的用法,但是__unsafe_unretained会更易造成野指针,
并且需要注意的是,尽管ARC式的内存管理是编译器的工作,但是附有_unsafe_unretained修饰符的变量不属于编译器的内存管理对象
可以看如下两个例子来区别:__unsafe_unretained和__weak
第一个例子:
__strongNSString *yourString = [[NSStringalloc] initWithUTF8String:"your string"];
__weak NSString *myString = yourString;yourString = nil;
__unsafe_unretainedNSString *theirString = myString;
//现在所有的指针都为nil
第二个例子:
__strongNSString *yourString = [[NSStringalloc] initWithUTF8String:"string 1"];
__weak NSString *myString = yourString;
__unsafe_unretained NSString *theirString = myString;
yourString =nil;
//现在yourString与myString的指针都为nil,而theirString不为nil,但是是野指针。
由此可以看到__unsafe_unretained是不安全的,不建议使用__unsafe_unretained。
__autoreleasing使用:
在c/c++,objective-c内存管理中有一条是:谁分配谁释放。 __autoreleasing则可以使对像延迟释放。比如你想传一个未初始化地对像引用到一个方法当中,在此方法中实始化此对像,那么这种情况将是__autoreleasing表演的时候。看个示例:
- (void) generateErrorInVariable:(__autoreleasingNSError **)paramError
{
NSArray *objects = [[NSArrayalloc] initWithObjects:@"A simple error",nil];
NSArray *keys = [[NSArrayalloc] initWithObjects:NSLocalizedDescriptionKey,nil];
NSDictionary *errorDictionary = [[NSDictionaryalloc] initWithObjects:objectsforKeys:keys];
*paramError = [[NSErroralloc] initWithDomain:@"MyApp"code:1 userInfo:errorDictionary];
}
-(void)test
{
NSError *error = nil;
[selfgenerateErrorInVariable:&error];
NSLog(@"Error = %@", error);
}
//被编译器翻译后就变为:
-(void)test
{
NSError *error = nil;
NSError * __autoreleasing tmp = error;
[selfgenerateErrorInVariable:&tmp];
error = tmp;
NSLog(@"Error = %@", error);
}
以上就是对__strong、__weak、__unsafe_unretained和__autoreleasing修饰符的理解