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;