//
// @property 日熬、屬性携冤、修飾符
// Created by mac on 2016/10/30.
// Copyright ? 2016年 Rock. All rights reserved.
//
1> @property是什么?
@property 是聲明屬性的語法卵皂,它可以快速的為實例變量創(chuàng)建存取器,并允許我們通過點語法使用存取器秩铆。
@property 是一個屬性訪問聲明,擴號內(nèi)支持以下幾個屬性(下面有講解)
@property 它提供成員變量的訪問方法的聲明灯变、也控制成員變量的訪問權(quán)限豺旬、控制多線程時成員變量的訪問環(huán)境。
@property 可以在interface柒凉,在協(xié)議protocol. 和類別category中使用族阅。
@property (attribute1 , attribute2, ...) 是property的官方表達方式
@property 功能:讓編譯器自動編寫一對與數(shù)據(jù)成員同名的方法聲明來省去讀寫方法的聲明。
@property 是Objective-C語言關(guān)鍵詞膝捞,與@synthesize (?s?nθ??sa?z 合成)配對使用坦刀。xcode4.5以及以后的版本,@synthesize可以省略蔬咬。@synthesize 合成訪問器方法鲤遥,實現(xiàn)@property所聲明的方法的定義。其實說直白就像是:@property聲明了一些成員變量的訪問方法 林艘,@synthesize則定義了由@property聲明的方法盖奈。他們之前的對應(yīng)關(guān)系是 @property 聲明方法,頭文件中申明的方法狐援。 @synthesize定義方法在.m中 Cpp文件中定義的方法
《存取器(accessory): 用于獲取和設(shè)置實例變量的方法钢坦。 用于獲取實例變量值的存取器是 getter, 用于設(shè)置實例變量值的存取器的存取器是 setter 》
聲明property的語法為:@property (參數(shù)1,參數(shù)2) 類型 名字;
如:@property(nonatomic,retain) UIWindow *window;
@property聲明的是屬性究孕,而類后面加{}聲明的是成員變量,屬性跟成員變量是一回事爹凹,
只是 @property將我們的成員變量公開出去讓外部類可以調(diào)用厨诸,
不允許外部訪問的統(tǒng)統(tǒng)寫在{}內(nèi)作為成員變量供自己內(nèi)部使用。
//-----------------------------------------------------
為了跟好的理解@property 來了解一下存取器:
2> 創(chuàng)建存取器 我們先看兩段代碼:
// Car.h
#import <Foundation/Foundation.h>
@interface Car : NSObject
{
// 實例變量
NSString *carName;
NSString *carType;
}
// setter
- (void)setCarName:(NSString *)newCarName;
// getter
- (NSString *)carName;
// setter
- (void)setCarType:(NSString *)newCarType;
// getter
- (NSString *)carType;
@end
//-----------------------------------------------------
上面的代碼中 carName 和 carType 就是 Car 的實例變量禾酱,并且可以看到 分別對這兩個實例變量聲明了get/set 法微酬,即存取器。
.m中實現(xiàn)
#import "Car.h"
@implementation Car
// setter
- (void)setCarName:(NSString *)newCarName
{
carName = newCarName;
}
// getter
- (NSString *)carName
{
return carName;
}
// setter
- (void)setCarType:(NSString *)newCarType
{
carType = newCarType;
}
// getter
- (NSString *)carType
{
return carType;
}
@end
颤陶、
上面代碼是對實例變量存取器的實現(xiàn)颗管。我們可以看到,存取器就是對實例變量進行賦值和取值滓走。按照約定賦值 法以set開頭垦江,取值方法以實例變量名命名。 我們看看如何使用:
// main.m
#import "Car.h"
int main(int argc, char * argv[])
{
@autoreleasepool {
Car *car = [[Car alloc] init];
[car setCarName:@"Jeep Cherokee"];
[car setCarType:@"SUV"];
NSLog(@"The car name is %@ and the type is %@",[car carName],[car carType]);
}
return 0;
}
上面的代碼中我們注意到闲坎,對象 Car 使用了消息語法疫粥,也就是使用括號的setter語法給存取器發(fā)送消息。
返回結(jié)果為:The car name is Jeep Cherokee and the type is SUV
//----------------------------------------------------------------------
2.1 使 @property創(chuàng)建存取器
// Car.h
#import <Foundation/Foundation.h>
@interface Car : NSObject
{
// 實例變量
NSString *carName;
NSString *carType;
}
@property(nonatomic,strong) NSString *carName;
@property(nonatomic,strong) NSString *carType;
@end
上面代碼中腰懂,我們使 @property 聲明兩個屬性梗逮,名稱與實例變量名稱相同
(讓我們先忽略 nonatomic 和 strong )。
// Car.m
#import "Car.h"
@implementation Car
@synthesize carName;
@synthesize carType;
@end
在.m 文件中我們使 @synthesize 自動生成這兩個實例變量的存取器绣溜,
并且隱藏了存取器慷彤,雖然我們看不到存取器,但它們確實是存在的怖喻。
// main.m
int main(int argc, char * argv[])
{
@autoreleasepool {
Car *car = [[Car alloc] init];
car.carName = @"Jeep Compass";
car.carType = @"SUV";
NSLog(@"The car name is %@ and the type is %@",
car.carName,car.carType);
}
return 0;
}
在上面的代碼中我們可以注意到底哗, Car 對象使用點語法給存取器發(fā)送消息,
并且get與set的語法是相同的锚沸,并且點語法可以根據(jù)語境判斷我們是要賦 值還是取值跋选。
當(dāng)然我們也依然可以使用消息語法來使用:
// main.m
int main(int argc, char * argv[])
{
@autoreleasepool {
Car *car = [[Car alloc] init];
// 點語法
// car.carName = @"Jeep Compass";
// car.carType = @"SUV";
//NSLog(@"The car name is %@ and the type is %@",car.carName,car.carType);
// 消息語法
[car setCarName:@"Jeep Compass"];
[car setCarType:@"SUV"];
NSLog(@"The car name is %@ and the type is %@",
[car carName],[car carType]);
}
return 0;
}
上面兩段代碼的執(zhí) 結(jié)果都是:
The car name is Jeep Compass and the type is SUV
總結(jié): @property 等同于在.h 件中聲明實例變量的get/set方法,
@synthesize 等同于在.m 件中實現(xiàn)實例變量的get/set方法哗蜈。
使@property 和 @synthesize 創(chuàng)建存取器 聲明兩個存取器方法
( getter 和 setter )更簡單前标。 且我們在使 屬性時可以使用點語法賦值或取值,
語法更簡單距潘,更符合面向?qū)ο缶幊獭?
//---------------------------------------------------------------------
2.2 不必單獨聲明實例變量
如果使用@Property 炼列,就不必單獨聲明實例變量了。
因為在沒有顯式提供實例變量聲明的前提下音比,
系統(tǒng)會自動幫你完成實例變量俭尖。我們通過以下代碼來說明:
// Car.h
#import <Foundation/Foundation.h>
@interface Car : NSObject
@property(nonatomic,strong) NSString *carName;
@property(nonatomic,strong) NSString *carType;
- (NSString *)carInfo;
@end
在.h 件中我們并沒有聲明實例變量,只是聲明了 carName和 carType
兩個屬性,以及 一個 carInfo方法稽犁,返回值為 NSString * 焰望。
// Car.m
#import "Car.h"
@implementation Car
- (NSString *)carInfo
{
return [NSString stringWithFormat:@"The car name is %@and the type is%@",_carName,_carType];
}
@end
在.m 件中我們可以注意到,在 carInfo方法中我們使用了 _carName 和 _carType 實例變量缭付,
這就是當(dāng)我們沒有顯式聲明實例變量時柿估,系統(tǒng)為我們自動生成的循未。命名規(guī)則是以 _ 為前綴陷猫,加上屬性名,
即 _propertyName 的妖。
其實在.m 件中實際是存在 @synthesize 聲明語句的绣檬,只是系統(tǒng)將其隱藏 了:
@synthesize carName = _carName;
@synthesize carType = _carType;
那么如果我們不喜歡默認的實例變量命名方法,
或者我們希望使用更有語義的名稱嫂粟,應(yīng)該怎么做呢娇未。其實很簡單:
// Car.m
#import "Car.h"
@implementation Car
@synthesize carName = i_am_car_name;
@synthesize carType = i_am_car_type;
- (NSString *)carInfo
{
return [NSString stringWithFormat:@"The car name is %@and the type is %@",
i_am_car_name,i_am_car_type];
}
@end
//----------------------------------------------------
2.3 再看一些介紹:關(guān)于類Class中的屬性property
在iOS第一版中,我們?yōu)檩敵隹谕瑫r聲明了屬性和底層實例變量星虹,
那時屬性是OC語言的一個新的機制零抬,
并且要求你必須聲明與之對應(yīng)的實例變量。 例如:
@interface MyViewController :UIViewController
{
UIButton *myButton;
}
@property (nonatomic, retain) UIButton *myButton;
@end
蘋果將默認編譯器從GCC轉(zhuǎn)換為LLVM(low level virtual machine)宽涌,
從此不再需要為屬性聲明實例變量了平夜。
如果LLVM發(fā)現(xiàn)一個沒有匹配實例變量的屬性,
它將自動創(chuàng)建一個以下劃線開頭的實例變量卸亮。
因此忽妒,在LLVM這個版本中,我們不再為輸出口聲明實例變量兼贸。
例如:MyViewController.h文件
@interface MyViewController :UIViewController
@property (nonatomic, retain) UIButton *myButton;
@end
```
在MyViewController.m文件中段直,編譯器也會自動的生成一個實例變量_myButton。
那么在.m文件中可以直接的使用_myButton實例變量溶诞,也可以通過屬性self.myButton.都是一樣的鸯檬。
注意這里的self.myButton其實是調(diào)用的myButton屬性的getter/setter方法。
這與C++中點的使用是有區(qū)別的螺垢,C++中的點可以直接訪問成員變量(也就是實例變量)喧务。
例如在OC中有如下代碼
.h文件:
@interface MyViewController :UIViewController
{
NSString *name;
}
@end
.m文件中,self.name 這樣的表達式是錯誤的甩苛。
xcode會提示你使用->,改成self->name就可以了蹂楣。因為OC中點表達式是表示調(diào)用方法,而上面的代碼中沒有name這個方法讯蒲。
OC語法關(guān)于點表達式的說明: {"點表達式(.)看起來與C語言中的結(jié)構(gòu)體訪問以及java語言匯總的對象訪問有點類似痊土,其實這是OC的設(shè)計人員有意為之。如果點表達式出現(xiàn)在等號 = 左邊墨林,該屬性名稱的setter方法將被調(diào)用赁酝。如果點表達式出現(xiàn)在右邊犯祠,該屬性名稱的getter方法將被調(diào)用。" } 所以在OC中點表達式其實就是調(diào)用對象的setter和getter方法的一種快捷方式, 例如:People.age = 18; 完全等價于 [People.age setAge:18];
```
以前的用法酌呆,聲明屬性跟與之對應(yīng)的實例變量:
@interface MyViewController :UIViewControlle
{
UIButton *myButton;
}
@property (nonatomic, retain) UIButton *myButton;
@end
這種方法基本上使用最多衡载,現(xiàn)在大部分也是在使用,因為很多開源的代碼都是這種方式隙袁。
但是ios5更新之后痰娱,蘋果是建議以以下的方式來使用:
@interface MyViewController :UIViewController
@property (nonatomic, retain) UIButton *myButton;
@end
因為編譯器會自動為你生成以下劃線開頭的實例變量_myButton,不需要自己手動再去寫實例變量菩收。而且也不需要在.m文件中寫@synthesize myButton梨睁;也會自動為你生成setter,getter方法娜饵。@synthesize的作用就是讓編譯器為你自動生成setter與getter方法坡贺。 @synthesize 還有一個作用,可以指定與屬性對應(yīng)的實例變量箱舞,例如@synthesize myButton = xxx遍坟;那么self.myButton其實是操作的實例變量xxx,而不是_myButton了晴股。
在實際的項目中愿伴,我們一般這么寫.m文件
@synthesize myButton;
這樣寫了之后,那么編譯器會自動生成myButton的實例變量队魏,以及相應(yīng)的getter和setter方法公般。注意:_myButton這個實例變量是不存在的,因為自動生成的實例變量為myButton而不是_myButton胡桨,所以現(xiàn)在@synthesize的作用就相當(dāng)于指定實例變量官帘;
如果.m文件中寫了@synthesize myButton;那么生成的實例變量就是myButton;如果沒寫@synthesize myButton;那么生成的實例變量就是_myButton昧谊。所以跟以前的用法還是有點細微的區(qū)別刽虹。
通過上述代碼可以看到,我們只需要通過 @synthesize 來聲明我們希望的實例變量名呢诬。
總結(jié):如果我們希望使用默認的實例變量命名顯式涌哲,那么我們在.m 件中 就不需要使 @synthesize 聲明,
系統(tǒng)會幫我們自動完成尚镰。如果我們希望自己命名實例變量命阀圾,那么我們就使 @synthesize 顯式聲明我們希望的實例變量名。
// @property 屬性描述 只要屬性描述過之后 就可以用對象名打點調(diào)用此屬性 例如:
@property NSString *name; //相當(dāng)于
1 . 聲明了一個屬性 叫做 NSString *_name;
2. 聲明并實現(xiàn)了一個set方法
- (void)setName:(NSString *)name;
3. 聲明并實現(xiàn)了 一個get方法
- (NSString *)name;
*****************************3狗唉、@property的特性*********************
@property 還有一些關(guān)鍵字初烘,它們都是有特殊作用的,
如上述代碼中的 nonatomic,strong :
@property(nonatomic,strong) NSString *carName;
主要屬性分為3類:
分別是:原子性肾筐,存取器控制哆料,內(nèi)存管理。
原子性 (Atomicity) 包含:nonatomic
讀寫屬性(Writability,有時也可以稱為存取器控制) 包含:readwrite / readonly
內(nèi)存管理(有時也可以稱為 setter語義,Setter Semantics)包含:assign / retain / copy
// ***********各控制權(quán)限的關(guān)鍵字意義如下:*****************
1吗铐、{
存取器控制/可讀性: readonly 东亦、readwrite
readwrite 、readonly:決定是否生成set訪問器唬渗,
readwrite 是默認屬性典阵,是可讀可寫特性、表明該屬性同時擁有 setter 和 getter方法的聲明與實現(xiàn) 谣妻。
readonly 是只讀特性 只會生成getter方法 不會生成setter方法 ;不希望屬性在類外改變,注意 :readonly關(guān)鍵字代表setter不會被生成萄喳, 所以它不可以和 copy/retain/assign組合使用卒稳。
@property(readwrite,....) valueType value;這個屬性是變量的默認屬性蹋半,就是如果你(readwrite and readonly都沒有使用,那么你的變量就是readwrite屬性)充坑,通過加入readwrite屬性你的變量就會有g(shù)et方法减江,和set方法。
@property(readonly,...) valueType value;這個屬性變量就是表明變量只有可讀方法捻爷,也就是說辈灼,你只能使用它的get方法。
有時候為了語意更明確可能需要定義訪問器的名字 修改方法名稱的關(guān)鍵字 :
getter=getterName也榄,setter=setterName巡莹,設(shè)置setter與getter的方法名 eg:
@property (nonatomic, setter = mySetter:,getter = myGetter) NSString *name;
最常用的是BOOL類型,一般情況下甜紫,BOOL類型的屬性的getter方法都是以is開頭的降宅。
如標(biāo)識View是否隱藏的屬性hidden∏舭裕可以這樣聲明:
@property (nonatomic,getter = isHidden ) BOOL hidden;
setter表示修改生成的setter方法的名稱腰根,不過一般不修改。
從OC 2.0開始拓型,我們能讓系統(tǒng)自動生成設(shè)置變量值的方法或獲取變量值的方法额嘿,
即系統(tǒng)會自動為我們生成setter/getter方法。
注意:默認的property行為有:atomic劣挫,assign册养,readwrite。
如果這樣使用:@property BOOL _flag;//代表這_flag有著atomic压固,assign球拦,readwrite三種行為。
所以我們一定要提防這種默認行為潛在的危險。
如:@property NSMutableArray *photoViews;//此時會有警告出現(xiàn)刘莹,因為NSMutableArray是一種obj類型阎毅,并且是 NSArray類型,根據(jù)前面的分析点弯,最好采用retain扇调。所以默認的assign會帶來警告提示。
}
2抢肛、{
內(nèi)存管理:
@property 有顯式的內(nèi)存管理策略狼钮。
這使得我們只需要看一眼 @property 聲明就明白它會怎樣對待傳遞的值。
************************************************
assign (默認): assign 用于值類型捡絮,
如 int 熬芜、 float 、 double 和 NSInteger 福稳, CGFloat 等表的單純的復(fù)制涎拉。
還包括不存在所有權(quán)關(guān)系的對象, 如常用的delegate的圆。
@property(nonatomic) int running;
@property(nonatomic,assign) int running;
以上兩段代碼是相同的鼓拧。
在 setter 方法中,采用直接賦值來實現(xiàn)設(shè)值操作:
-(void)setRunning:(int)newRunning{
_running = newRunning;
}
retian :在 setter 方法中越妈,需要對傳的對象進行引用計數(shù)加1的操作季俩。 簡單來說,就是對傳的對象擁有所有權(quán)梅掠,只要對該對象擁有所有權(quán)酌住,該對象就不會被釋放。如下代碼所 :
-(void)setName:(NSString*)_name{
//先判斷是否與舊對象一致阎抒,如果不一致 進行賦值酪我。
//因為如果是一個對象的話,進行if內(nèi)的代碼會造成一個極端的情況:
當(dāng)此name的retain為1時挠蛉,使用此次的set操作讓實例name提前釋放祭示,而達不到賦值的。
if ( name != _name){
[name release];
name = [_name retain];
}
}
strong : strong 是在IOS引入ARC的時候引用的關(guān)鍵字谴古,是retain的一個可選的替代质涛。
表示實例變量對傳入的對象要有所有權(quán)關(guān)系,即強引用掰担。strong跟retain的意思相同并產(chǎn)生相同的代碼汇陆,但是語意上更好更能體現(xiàn)對象的關(guān)系。
weak :在 setter 方法中带饱,需要對傳入的對象不進行引用計數(shù)加1的操作毡代。 簡單來說阅羹,就是對傳入的對象沒有所有權(quán),當(dāng)該對象引用計數(shù)為0時教寂,即該對象被釋放后捏鱼,weak 聲明的實例變量指向nil ,即實例變量的值為 0酪耕。
注: weak 關(guān)鍵字是IOS5引進的导梆,IOS5之前是不能使用該關(guān)鍵字的。
delegate 和 IBOutlet一般用 weak 來聲明迂烁。
copy :與 strong 類似看尼,但區(qū)別在于實例變量是對傳對象的副本擁有有所有權(quán),
在setter方法中盟步,首先復(fù)制傳入的參數(shù)藏斩,然后將原來的舊值release,新的數(shù)值復(fù)制上去却盘。
-(void)setName:(NSString*)newName{
if(newName!=name){
[name release];
name=[newName copy];
}
}
注意:Foundation中可復(fù)制的對象狰域,當(dāng)我們copy的是一個不可變的對象的時候,它的作用相當(dāng)與retain(cocoa做的內(nèi)存優(yōu)化)比如我們對NSString進行copy谷炸,copy得到的地址是不變的北专。
下面四段代碼中,第一段顯示的結(jié)果不會copy旬陡,而是retain.
NSString *sstr = [NSString stringWithFormat:@"dfa"];
NSLog(@"strassign:%p, count:%ld", sstr , [sstr retainCount]);
NSString *sstr2 = [sstr copy];
NSLog(@"strassign:%p, count:%ld", sstr2 , [sstr2 retainCount]);
NSString *sstr = [NSString stringWithFormat:@"dfa"];
NSLog(@"strassign:%p, count:%ld", sstr , [sstr retainCount]);
NSString *sstr2 = [sstr mutableCopy];
NSLog(@"strassign:%p, count:%ld", sstr2 , [sstr2 retainCount]);
NSMutableString *str = [NSMutableString stringWithFormat:@"dfa"];
NSLog(@"strassign:%p, count:%ld", str , [str retainCount]);
NSMutableString *str2 = [str copy];
NSLog(@"strassign:%p, count:%ld", str2 , [str2 retainCount]);
NSMutableString *str = [NSMutableString stringWithFormat:@"dfa"];
NSLog(@"strassign:%p, count:%ld", str , [str retainCount]);
NSMutableString *str2 = [str mutableCopy];
NSLog(@"strassign:%p, count:%ld", str2 , [str2 retainCount]);
*******************************************************************
//================我是分割線===============新的剖析================
assign、 retain 语婴、copy: 這些屬性用于指定set訪問器的語義描孟,
也就是說,這些屬性決定了以何種方式對數(shù)據(jù)成員賦予新值砰左。
assign:默認類型,setter方法直接賦值匿醒,不進行任何retain操作,
為了解決原類型與環(huán)循引用問題
retain:setter方法對參數(shù)進行release舊值缠导,再retain新值廉羔。所有實現(xiàn)都是這個順序
copy: setter方法進行Copy操作,與retain處理流程一樣僻造,先舊值release憋他,
再Copy出新的對象,retainCount為1髓削。這是為了減少對上下文的依賴而引入的機制竹挡。
copy是在你不希望a和b共享一塊內(nèi)存時會使用到。a和b各自有自己的內(nèi)存
(通過這些我們可以看出這些屬性和setter方法有關(guān)系立膛,
所以面試的或者筆試題會有讓寫出一個assign揪罕、retain梯码、copy方法)
//------------------------------------------------------
面試題中會有:試寫出 @property中帶retain和assign關(guān)鍵字,
通過@synthesize自動生成的的合成存取方法(set好啰、get方法)的實現(xiàn)代碼:
getter分析:
@property (nonatomic, retain) test*aTest;
@property (nonatomic, copy) test*aTest;
等效代碼:
-(void)aTest {
return aTest;
}
@property (retain) test* aTest;
@property (copy) test* aTest;
等效代碼:
-(void)aTest
{
[aTest retain];
return [aTest autorelease];
}
======== 貌似我是分割線 =====
setter分析:
@property (nonatomic, retain) test*aTest;
@property (retain) test* aTest;
等效于:
-(void)setaTest:(test *)newaTest {
if (aTest !=newaTest) {
[aTest release];
aTest = [newaTest retain];
}
}
======== 貌似我是分割線 =====
@property (nonatomic, copy) test*aTest;
@property (copy) test* aTest;
等效于:
-(void)setaTest:(test *)newaTest {
if (aTest != newaTest){
[aTest release];
aTest = [newaTest copy];
}
}
*******************************************************************
//------------------------第二輪解析---------------------------------
**************************** assign *******************************
1轩娶、{
assign 普通、直接賦值框往,索引計數(shù)不改變罢坝,一般常用于簡單數(shù)據(jù)類型,
如NSInteger,double,bool,CGFloat搅窿,C數(shù)據(jù)類型(int, float,double, char, 等等)常見委托設(shè)計模式嘁酿,以此來防止循環(huán)引用。assign是賦值特性男应,僅設(shè)置變量時闹司,setter方法將傳入?yún)?shù)賦值給實例變量;
(補充:
assign與weak沐飘,它們都是弱引用聲明類型游桩,最大的區(qū)別在那呢?
如果用weak聲明的變量在棧中就會自動清空耐朴,賦值為nil借卧。
如果用assign聲明的變量在棧中可能不會自動賦值為nil,就會造成野指針錯誤筛峭!
二铐刘、實例
他們常用在基本類型屬性,比如BOOL影晓,int等镰吵,還有就是delegate。
在使用delegate時挂签,需要注意疤祭,非ARC時是使用assign,但到了ARC時代饵婆,都建議使用weak勺馆,這樣更安全。
```
不管是在非ARC還是ARC侨核,使用assign時草穆,都需要注意釋放,
@property (nonatomic , assign) id <MyDelegate> delegate;
如果你寫的library比較早芹关,那時還是非ARC的续挟,你的delegate設(shè)成assign property
這樣是為了不造成circular reference
當(dāng)別人使用你的library的時候,記得在你自己dealloc的時候侥衬,把delegate設(shè)成nil诗祸,以避免crash的事情發(fā)生跑芳。
這在非ARC模式下是比較自然的,都會這么去做直颅,
當(dāng)myViewController 的 ratain count 變成0 博个,則會dealloc
同時在dealloc 中,也是一并把myClass release,則myClass 也跟著被release.
//MRC
- (void) dealloc {
myClass.delegate = nil ;
[myClass release];
[super dealloc];
}
但在ARC模式下功偿,使用方就不會有dealloc處理的習(xí)慣了
- (void) dealloc {
//myClass.delegate = nil ;
[myClass setDelegate:nil];
}
如果在ARC下盆佣,沒有做這個邏輯的話,當(dāng)頁面銷毀的時候械荷,
很可能出現(xiàn)delegate對象無效共耍,導(dǎo)致程序crash.
所以,在我們使用網(wǎng)上下載的開源庫或者時間比較久的代碼時吨瞎,
記得檢查delegate的修飾符痹兜,如果是assign的需要及時修改為weak。
@property (nonatomic , weak) id <MyDelegate> delegate;
###為什么基本數(shù)據(jù)類型用assgin?
iOS中的垃圾處理機制是根據(jù)一個對象的索引數(shù)來處理的颤诀,
為0的時候表示沒有地方使用該對象字旭,則該對象將被清除,
而基本數(shù)據(jù)類型不屬于對象崖叫,它的創(chuàng)建和使用都是在內(nèi)存中遗淳,
超出對應(yīng)方法體即被清除,所以不需要使用垃圾處理機制心傀,
無需記錄索引值屈暗,所以使用assgin
循環(huán)引用: 所有的引用計數(shù)系統(tǒng),都存在循環(huán)應(yīng)用的問題剧包。
循環(huán)引用:指針的是兩個對象中恐锦,你中有我,我中有你疆液。
跟java中的一對一很相似。
至于產(chǎn)生內(nèi)存泄露的原因:主要是相互之間強指針指著對方陕贮,
感覺跟java里面誰來hibernate設(shè)置誰來管理對方堕油。
(在這里我們引入了強指針與弱指針在ARC中會提到,這里不做解釋肮之。)
解決循環(huán)引用的方式:讓其中一方設(shè)置為assign掉缺。
多個對象之間不要封閉環(huán),如果出現(xiàn)封閉的環(huán)戈擒,那么環(huán)中所有的對象將得不到釋放眶明。
解決的方法,讓其中一端為虛線筐高。
例如下面的引用關(guān)系:
·對象a創(chuàng)建并引用到了對象b.
·對象b創(chuàng)建并引用到了對象c.
·對象c創(chuàng)建并引用到了對象b. 這時候b和c的引用計數(shù)分別是2和1搜囱。
當(dāng)a不再使用b丑瞧,調(diào)用release釋放對b的所有權(quán),因為c還引用了b蜀肘,
所以b的引用計數(shù)為1绊汹,b不會被釋放。b不釋放扮宠,c的引用計數(shù)就是1西乖,
c也不會被釋放。從此坛增,b和c永遠留在內(nèi)存中获雕。這種情況,
必須打斷循環(huán)引用收捣,通過其他規(guī)則來維護引用關(guān)系届案。
比如,我們常見的delegate往往是assign方式的屬性而不是retain方式 的屬性坏晦,
賦值不會增加引用計數(shù)萝玷,就是為了防止delegation兩端產(chǎn)生不必要的循環(huán)引用。
如果一個UITableViewController 對象a通過retain獲取了UITableView對象b的所有權(quán)昆婿,
這個UITableView對象b的delegate又是a球碉, 如果這個delegate是retain方式的,
那基本上就沒有機會釋放這兩個對象了仓蛆。自己在設(shè)計使用delegate模式時睁冬,
也要注意這點。因為循環(huán)引用而產(chǎn)生的內(nèi)存泄露也是Instrument無法發(fā)現(xiàn)的看疙,所以要特別小心豆拨。
###assign和weak的區(qū)別
在ARC中的assign和weak可以說非常相像,導(dǎo)致有很多人誤以為他們是一摸一樣的能庆,
在任何時候都可以劃等價施禾,但事實卻不是這樣。
有人問搁胆,id類型的delegate屬性到底是用assign還是weak弥搞?
@property (weak, nonatomic) id<AnyDelegate> delegate;
@property (assign, nonatomic) id<AnyDelegate> delegate;
大家眾說紛紜,說都可以的渠旁,說assign的攀例,說weak的都有,下面我們來看一本書中的描述:
“The main difference between weak and assign is that the with weak,
once the object being pointed to is no longer valid,
the pointer is nilled out. Assigning the pointer the value nil avoids
many crashes as messages sent to nil are essentially no-ops”
Excerpt From: Daniel H Steinberg.
“Developing iOS 7 Apps for iPad and iPhone.”
Dim Sum Thinking, Inc, 2014. iBooks. iTunes - Books
大致的意思是說顾腊,weak比assign多了一個功能就是當(dāng)屬性所指向的對象消失的時候
(也就是內(nèi)存引用計數(shù)為0)會自動賦值為nil粤铭,
這樣再向weak修飾的屬性發(fā)送消息就不會導(dǎo)致野指針操作crash。
可能不太好理解下面我寫了一個演示程序杂靶。
OC:
// ViewController.m
// weak與assgin的區(qū)別:
#import "ViewController.h"
@interface ViewController ()
@property (nonatomic,weak) id weakPoint;
@property (nonatomic,assign) id assignPoint;
@property (nonatomic,strong) id strongPoint;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.strongPoint = [NSDate date];
NSLog(@"strong屬性:%@",self.strongPoint);
self.weakPoint = self.strongPoint;
self.assignPoint = self.strongPoint;
self.strongPoint = nil;
NSLog(@"weak屬性:%@",self.weakPoint);
// NSLog(@"assign屬性:%@",self.assignPoint);
}
@end
當(dāng)程序中的注釋被打開時梆惯,運行程序有可能會崩潰(有時候不崩潰酱鸭,你可能需要多運行幾次),
這是因為當(dāng)assign指針?biāo)赶虻膬?nèi)存被釋放(釋放并不等于抹除加袋,只是引用計數(shù)為0)凛辣,
不會自動賦值nil,這樣再引用self.assignPoint就會導(dǎo)致野指針操作职烧,
如果這個操作發(fā)生時內(nèi)存還沒有改變內(nèi)容扁誓,依舊可以輸出正確的結(jié)果,
而如果發(fā)生時內(nèi)存內(nèi)容被改變了蚀之,就會crash蝗敢。
結(jié)論:在ARC模式下編程時,指針變量一定要用weak修飾足删,
只有基本數(shù)據(jù)類型和結(jié)構(gòu)體需要用assgin寿谴,例如delegate,
一定要用weak修飾失受。
)
}
******************************* retain ********************************
#2讶泰、{
retain:指針的拷貝,retain表示持有特性拂到,使用的是原來的內(nèi)存空間笛匙。
希望獲得原對象的所有權(quán)時全闷,對其他NSObject和其子類引用計數(shù)在原有基礎(chǔ)上加1逛薇。
setter方法將傳入?yún)?shù)先保留凡纳,再賦值,傳入?yún)?shù)的retaincount會+1领铐,
此屬性只能用于Objective-C對象類型悯森,而不能用于Core Foundation對象。
(原因很明顯绪撵,retain會增加對象的引用計數(shù)瓢姻,
而基本數(shù)據(jù)類型或者Core Foundation對象都沒有引用計數(shù))。
copy:也用于對象音诈,對象的拷貝汹来,copy表示賦值特性,希望獲得原對象的副本而不改變原對象內(nèi)容時改艇,
用來復(fù)制對象,新申請一塊內(nèi)存空間坟岔,并把原始內(nèi)容復(fù)制到那片空間谒兄。新對象的索引計數(shù)為1。
此屬性只對那些實行了NSCopying協(xié)議的對象類型有效社付。
很多Objective-C中的object最好使用用retain承疲,一些特別的object(例如:string)使用copy邻耕。
一般字符串(NSString)使用copy,F(xiàn)oundation中的不可變對象使用copy效果相當(dāng)于retain燕鸽,
只是引用計數(shù)+1兄世。setter方法將傳入對象復(fù)制一份;需要完全一份新的變量時啊研。
}
******************************* atomic ********************************
3御滩、{
***#對原子性的理解:#***
1、原子性就是說一個操作不可以被中途CPU暫停然后調(diào)度, 即不能被中斷, 要不就執(zhí)行完, 要不就不執(zhí)行. 如果一個操作是原子性的,那么在多線程環(huán)境下, 就不會出現(xiàn)變量被修改等奇怪的問題党远。原子操作就是不可再分的操作削解,在多線程程序中原子操作是一個非常重要的概念,它常常用來實現(xiàn)一些同步機制沟娱,同時也是一些常見的多線程Bug的源頭氛驮。當(dāng)然,原子性的變量在執(zhí)行效率上要低些济似。
2矫废、關(guān)于異步與同步:并非同步就是不好,我們通常需要同時進行多個操作砰蠢,這時使用異步蓖扑,而對于程序來說,一般就是使用多線程娩脾,然而我們很多時候需要在多個線程間訪問共享的數(shù)據(jù)赵誓,這個時候又需要同步來保證數(shù)據(jù)的準確性或訪問的先后次序。當(dāng)有多個線程需要訪問到同一個數(shù)據(jù)時柿赊,OC中俩功,我們可以使用@synchronized(變量)來對該變量進行加鎖(加鎖的目的常常是為了同步或保證原子操作)。
3碰声、**nonatomic:**非原子性诡蜓,是直接從內(nèi)存中取數(shù)值,因為它是從內(nèi)存中取得數(shù)據(jù)胰挑,它并沒有一個加鎖的保護來用于CPU中的寄存器計算Value蔓罚,它只是單純的從內(nèi)存地址中,當(dāng)前的內(nèi)存存儲的數(shù)據(jù)結(jié)果來進行使用瞻颂。在多線環(huán)境下可提高性能豺谈,但無法保證數(shù)據(jù)同步。
**4贡这、atomic:**原子性茬末,如果你沒有對對象進行一個聲明(atomic or nonatomic),那么系統(tǒng)會默認你選擇的是atomic。默認值是atomic丽惭,為原子操作(默認): atomic 意為操作是原子性的击奶,意味著只有一個線程 訪問實例變量。atomic是線程安全的责掏, 少在當(dāng)前的存取器上是安全的柜砾。 它是一個默認的特性,但是很少使 换衬,因為比較影響效率痰驱,這跟ARM平臺和內(nèi)部鎖機制有關(guān)。
** nonatomic:**非原子性操作冗疮,非原子性訪問萄唇,不加同步,多線程并發(fā)訪問會提高性能术幔。如果不加此屬性另萤,則默認是兩個訪問方法都為原子型事務(wù)訪問。鎖被加到所屬對象實例級(所以不加nonatomic對與多線程是安全的)诅挑,nonatomic 跟 atomic 剛好相反四敞。非原子性操作,可以被多個線程訪問拔妥。它的效率比atomic快忿危。但不能保證在多線程環(huán)境下的安全性,在單線程和明確只有一個線程訪問的情況下廣泛使 没龙。
atomic和nonatomic用來決定編譯器生成的getter和setter是否為原子操作铺厨。在多線程環(huán)境下,原子操作是必要的硬纤,否則有可能引起錯誤的結(jié)果解滓。atomic表示多線程安全,一般使用nonatomic
**5筝家、原子(atomic) 跟非原子(non-atomic)屬性有什么區(qū)別?**
1). atomic 提供多線程安全洼裤。atomic是OC使用的一種線程保護技術(shù),基本上來講溪王,是防止在寫未完成的時候被另外一個線程讀取腮鞍,造成數(shù)據(jù)錯誤。而這種機制是耗費系統(tǒng)資源的莹菱,所以在iPhone這種小型設(shè)備上移国,如果沒有使用多線程間的通訊編程,那么nonatomic是一個非常好的選擇
2). non-atomic 在自己管理內(nèi)存的環(huán)境中道伟,解析的訪問器保留并自動釋放返回的值桥狡,如果指定了 nonatomic ,那么訪問器只是簡單地返回這個值。
}
//
********類別中的屬性property*************************
類與類別中添加的屬性要區(qū)分開來裹芝,因為類別中只能添加方法,不能添加實例變量! ! !
經(jīng)常會在iOS的代碼中看到在類別中添加屬性娜汁,這種情況下嫂易,是不會自動生成實例變量的。
比如在:UINavigationController.h文件中會對UIViewController類進行擴展
@interface UIViewController (UINavigationControllerItem)
@property(nonatomic,readonly,retain) UINavigationItem *navigationItem;
@property(nonatomic) BOOL hidesBottomBarWhenPushed;
@property(nonatomic,readonly,retain) UINavigationController *navigationController;
@end
這里添加的屬性掐禁,不會自動生成實例變量怜械,這里添加的屬性其實是添加的getter與setter方法。
注意一點傅事,匿名類別(匿名擴展)是可以添加實例變量的缕允,非匿名類別是不能添加實例變量的,
只能添加方法蹭越,或者屬性(其實也是方法)障本。
· 成員變量用于類內(nèi)部,無需與外界接觸的變量响鹃。
· 根據(jù)成員變量的私有性驾霜,為了方便訪問,所以就有了屬性變量买置。
屬性變量的好處就是允許讓其他對象訪問到該變量粪糙。
當(dāng)然,你可以設(shè)置只讀或者可寫等忿项,設(shè)置方法也可自定義蓉冈。所以,
屬性變量是用于與其他對象交互的變量轩触。
一些建議:
1.如果只是單純的private變量寞酿,最好聲明在implementation里.
2.如果是類的public屬性,就用property寫在.h文件里
3.如果自己內(nèi)部需要setter和getter來實現(xiàn)一些東西怕膛,就在.m文件的類目里用property來聲明
//--------------------------------------------------------
.h中的interface的大括號{}之間的實例變量熟嫩,.m中可以直接使用;
.h中的property變量褐捻,.m中需要使用self.propertyVariable的方式
使用propertyVariable變量
// ***第三輪解析 在MRC中的@property ********
#1掸茅,assign :簡單賦值,不更改索引計數(shù)
假設(shè)你用alloc分配了一塊內(nèi)存柠逞,并且把它的地址賦值給了指針a昧狮,
后來你希望指針b也共享這塊內(nèi)存,于是你又把a賦值給(assign)了b板壮。
此時a 和b指向同一塊內(nèi)存逗鸣,請問當(dāng)a不再需要這塊內(nèi)存,能否直接釋放它?
答案是否定的撒璧,因為a并不知道b是否還在使用這塊內(nèi)存透葛,
如果a釋放了,那么b在使用這塊內(nèi)存的時候會引起程序crash掉
應(yīng)用場合:對基礎(chǔ)數(shù)據(jù)類型 (例如NSInteger卿樱,CGFloat)
和C數(shù)據(jù)類型(int, float, double, char, 等)
適用簡單數(shù)據(jù)類型僚害、 特例 delegate
//--------------------------------------------------------
#2,retain:與strong相對應(yīng)繁调,使用了引用計數(shù)萨蚕,retain+1,release -1;
當(dāng)引用 計數(shù)為0時,dealloc會被調(diào)用蹄胰,內(nèi)存被釋放
//-------------------------------------------------------
#3岳遥,copy:用于非共享內(nèi)存時,每個指針有自己的內(nèi)存空間
copy 當(dāng)屬性是NSString數(shù)據(jù)類型的時候就使用copy
copy 此特質(zhì)所表達的所屬關(guān)系與strong類似裕寨。然而設(shè)置方法并不保留新值浩蓉,而是將其“拷貝”
copy與retain的具體區(qū)別為:
copy其實是建立了一個相同的對象,而retain只是保存其對象帮坚,并且其計數(shù)值+1妻往。例如:
一個NSString對象,地址為0×1000试和,內(nèi)容為@”string”
copy到另外一個NSString之后讯泣,地址為0×2000,內(nèi)容相同阅悍,
新的對象retain為1好渠,舊有對象沒有變化
retain到另外一個NSString之后,地址相同(建立一個指針节视,指針拷貝)拳锚,內(nèi)容當(dāng)然相同,
但是這個新對象的retain值+1寻行,并釋放舊的對象霍掺。
因此,retain是指針拷貝拌蜘,copy是內(nèi)容拷貝杆烁。
```
#4,atomic 默認屬性
A简卧,當(dāng)一個變量聲明為atomic時兔魂,意味著在多線程中只能有一個線程能對它進行訪問
B,當(dāng)一個變量聲明為atomic時举娩,該變量為線程安全型析校,但是會影響訪問速度构罗,
C,當(dāng)一個變量聲明為atomic時智玻,在非ARC編譯環(huán)境下遂唧,
需要設(shè)置訪問鎖來保證對該變量進行正確的get/set
atomicity的默認值是atomic,讀取函數(shù)為原子操作尚困。
atomic是保證讀取變量是線程安全的蠢箩,即它會保證每次getter和setter的操作都會正確的執(zhí)行完畢,
而不用擔(dān)心其它線程在你get的時候set事甜,可以說保證了某種程度上的線程安全。```
# 5滔韵,nonatomic
A逻谦,當(dāng)一個變量聲明為nonatomic時,意味著多個線程可以同時對其進行訪問
B陪蜻,當(dāng)一個變量聲明為nonatomic時邦马,它是非線程安全型,訪問速度快宴卖;
C滋将,當(dāng)一個變量聲明為nonatomic時,當(dāng)兩個不同的線程對其訪問時症昏,容易失控随闽。
nonatomic是不能保證線程安全的。但是nonatomic比atomic速度要快肝谭。
這也是為什么property基本上都用nonatomic了掘宪。
僅僅靠atomic來保證線程安全是不可能的,要寫出線程安全的代碼攘烛,還是需要有同步和互斥機制魏滚。
# 總結(jié):atomic和nonatomic用來決定編譯器生成的getter和setter是否為原子操作。
在多線程環(huán)境下坟漱,原子操作是必要的鼠次,否則有可能引起錯誤的結(jié)果。
加了atomic芋齿,setter函數(shù)會變成下面這樣:
if (property != newValue) {
[property release];
property = [newValue retain];
}
# strong與weak是由ARC新引入的對象變量屬性
6,strong: ARC中默認屬性腥寇,等于MRC中的retain, 與retain相對應(yīng),“擁有關(guān)系” 為這種屬性設(shè)置新值時沟突,
設(shè)置方法先保留新值花颗,并釋放舊值,然后再將新值設(shè)置上去惠拭,strong是在iOS引入ARC的時候引入的關(guān)鍵字扩劝,
是retain的一個可選的替代庸论。表示實例變量對傳入的對象要有所有權(quán)關(guān)系,即強引用棒呛。
strong跟retain的意思相同并產(chǎn)生相同的代碼聂示,但是語意上更好更能體現(xiàn)對象的關(guān)系。
應(yīng)用場景:strong屬性用于ARC中
@property (strong,nonatomic) ViewController *viewController;
7,weak: 與assign 相對應(yīng)簇秒,“非擁有關(guān)系” 為這種屬性設(shè)置新值時鱼喉,設(shè)置方法既不保留新值,也不釋放舊值趋观。
此特質(zhì)同assign類似扛禽,然而屬性所指的對象遭到摧毀時,屬性也會被清空(nil out)皱坛,在setter方法中编曼,
需要對傳入的對象不進行引用計數(shù)加1的操作,和assign相似。簡單來說剩辟,就是對傳入的對象沒有所有權(quán)掐场,
當(dāng)該對象引用計數(shù)為0時,即該對象被釋放后贩猎,用weak聲明的實例變量指向nil熊户,即實例變量的值為0。
應(yīng)用場景:用于IBOutlets,如吭服,UIViewController的子類嚷堡,即一般的控件。
@property (weak, nonatomic) IBOutlet UIButton *myButton;
#// 8噪馏、strong與weak的區(qū)別舉例:
前提:我們把要用strong或者weak的對象比作一只風(fēng)箏麦到,風(fēng)箏想掙脫線的束縛,自由飛翔去欠肾,
如果此時有一根線瓶颠,那么這只風(fēng)箏就掙脫不了
過程分析:
strong屬性的變量:當(dāng)我們把指向一只風(fēng)箏的變量聲明為strong時,此時刺桃,你就擁有控制這只風(fēng)箏的線
假如此時有五個人同時控制這只風(fēng)箏(即這只風(fēng)箏對象有三個strong類型的變量指向它)粹淋,
那么只有一種情況,這只風(fēng)箏才會掙脫掉線的束縛:這三個人都放掉手中的線瑟慈,(release掉)
#weak屬性的變量:當(dāng)我們把指向一只風(fēng)箏的變量聲明為weak時桃移,此時,就像站在旁邊看風(fēng)箏的觀眾們一樣葛碧,
當(dāng)上面的三個人還握著手中的線時借杰,他們只能看到風(fēng)箏,并不能控制它进泼,他們能做的只能是用手指指向風(fēng)箏蔗衡,
并大喊纤虽,“看,那只風(fēng)箏飛得真高绞惦!”逼纸,然而,當(dāng)上面的三個人把手中的線都放掉時济蝉,此時杰刽,風(fēng)箏飛走了,
看不見了王滤,不管有再多的觀眾贺嫂,他們再也看不到風(fēng)箏了,
這個故事告訴我們一個道理:
當(dāng)strong類型的指針被釋放掉之后雁乡,所有的指向同一個對象的weak指針都會被清零涝婉。
ARC引入了新的對象的新生命周期限定,即零弱引用蔗怠。
如果零弱引用指向的對象被dealloc的話,零弱引用的對象會被自動設(shè)置為nil吩跋。
#(_strong強指針標(biāo)識符寞射,默認所有的指針都是強指針)
作用:只要強指針指向的對象,那么這個對象就不會被釋放锌钮。
只要沒有強指針指向的對象桥温,那么這個對象將會被立即被釋放。
#(_weak弱指針標(biāo)識符)
弱指針:不參與內(nèi)存管理梁丘,對內(nèi)存管理沒有影響侵浸。不會影響對象的回收。
#注意:不要使用一個弱指針指向一個剛剛創(chuàng)建出來的對象氛谜,
一旦這樣做掏觉,剛創(chuàng)建出來的對象馬上銷毀,在OC中也是自動銷毀機制值漫。
當(dāng)出現(xiàn)循環(huán)引用的時候就必須要讓一端使用弱指針澳腹。
###強引用與弱引用的廣義區(qū)別:
強引用也就是我們通常所講的引用,其存亡直接決定了所指對象的存亡杨何。如果不存在指向一個對象的引用酱塔,
并且此對象不再顯示列表中,則此對象會被從內(nèi)存中釋放危虱。
弱引用除了不決定對象的存亡外羊娃,其他與強引用相同。即使一個對象被持有無數(shù)個若引用埃跷,
只要沒有強引用指向他蕊玷,那麼其還是會被清除邮利。沒辦法,還是 “強哥” 有面子集畅。
簡單講strong 等同 retain近弟,weak比assign多了一個功能,
當(dāng)對象消失后自動把指針變成nil挺智,好處不言而喻祷愉。
###強引用(strong)和弱引用(weak)的一個笑話(便于理解):
把對象想象成一條狗,它要跑 (be deallocated)赦颇。強指針就像一條拴在狗脖子上的狗鏈二鳄;
只要攥在手里,狗就跑不了媒怯;如果5個人攥著5條狗鏈都拴著狗 (5個強指針指向?qū)ο?订讼,
除非5條狗鏈都撒開,否則狗就跑不了扇苞。
弱指針就像是孩子指著狗喊“看欺殿!狗!”鳖敷;只要狗鏈還拴著狗脖苏,孩子就能指著狗喊。
當(dāng)所有狗鏈都撒開定踱,不管有多少孩子指著狗喊棍潘,狗都跑了。當(dāng)最后一個強指針不再指向?qū)ο螅? 對象就會被釋放崖媚,所有弱指針清零亦歉。我們什么時候使用弱指針呢?
只有當(dāng)你想避免保留循環(huán) (retain cycles,) 時畅哑,我們才使用它肴楷。
@property(strong) MyClass *myObject;
相當(dāng)于@property(retain) MyClass *myObject;
@property(weak) MyOtherClass *delegate;
相當(dāng)于@property(assign) MyOtherClass *delegate;
//-----------------------------------------------------------
9、,unsafe_unretauined
用在ARC編譯環(huán)境下敢课,在此環(huán)境下阶祭,與assign相似。它只是告訴ARC如何正確地調(diào)用聲明為unsafe_unretauined變量的retain和release
但是它適用于“對象類型”(object type)直秆,該特質(zhì)表達一種“非擁有關(guān)系”(“不保留”濒募,unretained),
當(dāng)目標(biāo)對象遭到摧毀時圾结,屬性值不會自動清空(“不安全”瑰剃,unsafe),這一點與weak有區(qū)別
//------------------------------------------------------------
在ARC中的@property 中 strong 對應(yīng)所有的普通 OC對象 copy 對應(yīng)字符串 筝野、
assign 基本數(shù)據(jù)類型 晌姚、weak 對于循環(huán)應(yīng)用的時候粤剧,必須保證一段使用的是weak。
```
#自動釋放池:(自動釋放池是一個棧)
autorelease: 延長對象的釋放生命周期挥唠。 作用: 把對象放進離自己最近的那個自動釋放池中抵恋。
(它與對象在何地創(chuàng)建沒有關(guān)系,只要標(biāo)記上就放進離自己最近的那個自動釋放池中宝磨。)
當(dāng)自動釋放池銷毀的時候弧关,它會把放在池中的所有對象進行一次release操作。
調(diào)用幾次autorelease唤锉,在自動釋放池銷毀的時候就調(diào)用幾次release操作世囊。
在自動釋放池中,只要是使用getter方法 構(gòu)造方法返回來的對象都是放在池中窿祥。
#注意:
在iOS 5(Xcode 4.2)以后加入了ARC機制株憾,ARC(automatic Reference Counting)自動內(nèi)存管理
ARC中編譯器的特性:編譯器會在適當(dāng)?shù)臅r候,
加入內(nèi)存管理的代碼!!! 不需要再調(diào)用retain/release方法管理內(nèi)存了晒衩,
但這并不是說ARC會自動回收內(nèi)存嗤瞎,它只是自動加入了retain/release的代碼,
OC的內(nèi)存管理機制依然是 !!! 計數(shù)機制 !!!听系。
assign生成的set方法中依然不會被自動加入retain/release代碼猫胁。
*/