iOS5中加入了新知识,就是ARC,其实我并非很喜欢它,由于习惯了本身管理内存。可是学习仍是颇有必要的。html
在iOS开发过程当中,属性的定义每每与retain, assign, copy有关,我想你们都很熟悉了,在此我也不介绍,网上有不少相关文章。java
如今咱们看看iOS5中新的关键字strong, weak, unsafe_unretained. 能够与之前的关键字对应学习strong与retain相似,weak与unsafe_unretained功能差很少(有点区别,等下会介绍,这两个新 关键字与assign相似)。在iOS5中用这些新的关键字,就能够不用手动管理内存了,从java等其它语言转过来的程序员很是受用。c++
strong关键字与retain关似,用了它,引用计数自动+1,用实例更能说明一切程序员
@property (nonatomic, strong) NSString *string1; objective-c
@property (nonatomic, strong) NSString *string2; app
有这样两个属性,函数
@synthesize string1; 学习
@synthesize string2; this
猜一下下面代码将输出什么结果?atom
self.string1 = @"String 1";
self.string2 = self.string1;
self.string1 = nil;
NSLog(@"String 2 = %@", self.string2);
结果是:String 2 = String 1
因为string2是strong定义的属性,因此引用计数+1,使得它们所指向的值都是@"String 1", 若是你对retain熟悉的话,这理解并不难。
接着咱们来看weak关键字:
若是这样声明两个属性:
@property (nonatomic, strong) NSString *string1;
@property (nonatomic, weak) NSString *string2;
并定义
@synthesize string1;
@synthesize string2;
再来猜一下,下面输出是什么?
self.string1 = @"String 1";
self.string2 = self.string1;
self.string1 = nil;
NSLog(@"String 2 = %@", self.string2);
结果是:String 2 = null
分析一下,因为self.string1与self.string2指向同一地址,且string2没有retain内存地址,而 self.string1=nil释放了内存,因此string1为nil。声明为weak的指针,指针指向的地址一旦被释放,这些指针都将被赋值为 nil。这样的好处能有效的防止野指针。在c/c++开发过程当中,为什么大牛都说指针的空间释放了后,都要将指针赋为NULL. 在这儿用weak关键字帮咱们作了这一步。
接着咱们来看unsafe_unretained
从名字能够看出,unretained且unsafe,因为是unretained因此与weak有点相似,可是它是unsafe的,什么是unsafe的呢,下面看实例。
若是这样声明两个属性:
并定义
@property (nonatomic, strong) NSString *string1;
@property (nonatomic, unsafe_unretained) NSString *string2;
再来猜一下,下面的代码会有什么结果?
self.string1 = @"String 1";
self.string2 = self.string1;
self.string1 = nil;
NSLog(@"String 2 = %@", self.string2);
请注意,在此我并无叫你猜会有什么输出,由于根本不会有输出,你的程序会crash掉。
缘由是什么,其实就是野指针形成的,因此野指针是可怕的。为什么会形成野指针呢?同于用unsafe_unretained声明的指针,因为 self.string1=nil已将内存释放掉了,可是string2并不知道已被释放了,因此是野指针。而后访问野指针的内存就形成crash. 因此尽可能少用unsafe_unretained关键字。
strong,weak, unsafe_unretained每每都是用来声明属性的,若是想声明临时变量就得用__strong, __weak, __unsafe_unretained, __autoreleasing, 其用法与上面介绍的相似。
仍是看看实例吧。
__strong NSString *yourString = @"Your String";
__weak NSString *myString = yourString;
yourString = nil;
__unsafe_unretained NSString *theirString = myString;
//如今全部的指针都为nil
再看一个:
__strong NSString *yourString = @"Your String";
__weak NSString *myString = yourString;
__unsafe_unretained NSString *theirString = myString;
yourString = nil;
//如今yourString与myString的指针都为nil,而theirString不为nil,可是是野指针。
__autoreleasing的用法介绍:
在c/c++,objective-c内存管理中有一条是:谁分配谁释放。 __autoreleasing则可使对像延迟释放。好比你想传一个未初始 化地对像引用到一个方法当中,在此方法中实始化此对像,那么这种状况将是__autoreleasing表演的时候。看个示例:
- (void) generateErrorInVariable:(__autoreleasing NSError **)paramError{
NSArray *objects = [[NSArray alloc] initWithObjects:@"A simple error", nil];
NSArray *keys = [[NSArray alloc] initWithObjects:NSLocalizedDescriptionKey, nil];
NSDictionary *errorDictionary = [[NSDictionary alloc] initWithObjects:objects forKeys:keys];
*paramError = [[NSError alloc] initWithDomain:@"MyApp" code:1 userInfo:errorDictionary];
}
-(void)test
{
NSError *error = nil;
[self generateErrorInVariable:&error];
NSLog(@"Error = %@", error);
}
这样即使在函数内部申请的空间,在函数外部也可使用,一样也适合谁分配谁释放的原则。
一样下面的代码也是相似缘由, 只不过在没有开启ARC的状况下适用:
-(NSString *)stringTest
{
NSString *retStr = [NSString stringWithString:@"test"];
return [[retStr retain] autorelease];
}
开启ARC后,应改成:
-(NSString *)stringTest
{
__autoreleasing NSString *retStr = [NSString alloc] initWithString:@"test"];
return retStr;
}
These attributes specify the semantics of a set accessor. They are mutually exclusive.
strong
Specifies that there is a strong (owning) relationship to the destination object.
weak
Specifies that there is a weak (non-owning) relationship to the destination object.
If the destination object is deallocated, the property value is automatically set to nil
.
(Weak properties are not supported on OS X v10.6 and iOS 4; use assign
instead.)
copy
Specifies that a copy of the object should be used for assignment.
The previous value is sent a release
message.
The copy is made by invoking the copy
method. This attribute is valid only for object types, which must implement the NSCopying
protocol.
assign
Specifies that the setter uses simple assignment. This attribute is the default.
You use this attribute for scalar types such as NSInteger
and CGRect
.
retain
Specifies that retain
should be invoked on the object upon assignment.
The previous value is sent a release
message.
In OS X v10.6 and later, you can use the __attribute__
keyword to specify that a Core Foundation property should be treated like an Objective-C object for memory management:
@property(retain) __attribute__((NSObject)) CFDictionaryRef myDictionary;