arc是在編譯的時候插入**來確信讓物件能夠按需要來存在。arc同樣是以引用計數為基礎。你可以選擇在以檔案或者專案為單位不使用arc。
但是建議盡量最好使用arc,首先,編譯器為你做記憶體管理往往比你自己要更優秀,其次,arc導致的效率損失在ui面前基本可以忽略不計。
arc有以下強制規則:
1. 你不能顯示的呼叫dealloc,實現或呼叫retain,release,retaincount,autorelease。
你可以實現自己的dealloc,目的是為了把**設定為空,或者編譯的時候沒有用到arc的**。
2. 不能使用nsallocateobject 和 nsdeallocateobject
3. 不能在c結構體中使用物件指標 ---原因
4. 不能直接轉換id 和 void *
5. 不能使用nsautoreleasepool,被更有效率的@autoreleasepool取代了。
6. 不能直接使用以new開頭的accessor,意味著不能使用以new開頭的屬性,除非你指定乙個不同的名字。如下:
//won't work
@property
nsstring
*newtitle;
//works
@property
(getter
= thenewtitle) nsstring *newtitle;
arc引入了新的關於變數生命週期的限定詞。
__strong 預設的限定符,只要有強指標指向物件,就可以一直存活
__weak 指定乙個引用,這個引用不能保持這個引用的物件存活,沒有強物件指向它的話,弱引用就會被設定為nil
__unsafe_unretained 這個引用不能保持這個引用的物件存活,沒有強物件指向它的話,弱引用就不會被設定為nil,如果它指向的物件釋放了的話,這個指標就成為懸掛指標。
__autoreleasing 用來代表通過引用傳遞並且在返回時自動釋放的引數。
必須正確的使用這些限定符。
nsstring
* __weak
string = [[nsstring alloc] initwithformat:
@"first name: %@"
, [self
firstname]];
nslog(
@"string: %@"
, string);
這個weak使用就是不恰當的,因為沒有任何強指標指向string,string立即就會被釋放了。
棧變數都被初始化為nil。
你需要注意通過引用傳遞的物件。
nserror
*error;
bool
ok = [
myobject
performoperationwitherror:&
error];
-(bool
)performoperationwitherror:(
nserror
* __autoreleasing
*)error;
這個呼叫實際的**是:
nserror
* __strong
error;
nserror
* __autoreleasing
tmp =
error
;bool
ok = [
myobject
performoperationwitherror:&
tmp];
error = tmp;
因為形式引數是__autorelease和實際引數是__strong,所以編譯器會建立臨時變數。
arc需要在你的init方法中
把[super init]的返回值賦給你的self
self
= [super
init
];if
(self)
struct mystruct
因為x預設是強型別,編譯器不能安全地合成所有以使其正常工作所需的**。比如你把乙個指向該結構的指標傳遞給別的函式,結構體裡面的id必須在結構被free掉之前釋放,但是編譯器不能可靠的做到這些。因此在arc中不能在結構體中使用強物件。可以使用以下解決方案:
1. 使用objective-c objects 代替結構體,這是最好的方式
2 使用void*替代。
3. 使用_unsafe_unretained限定符來比標示物件引用
struct mystruct
當然這可能是有問題的,是不安全的,如果該物件能從指標下被釋放。但是它對那些像字串常量這樣永遠不能改變的東西是非常有用的。
管理 toll-free轉換
在許多cocoa應用中,需要用到core foundation型別的物件。編譯器不能自動管理core foundation物件,需要呼叫cfretain和cfrelease類似的core foundation記憶體管理規則。
當你需要轉換objective c和core foundation物件時,需要使用cast函式或者core foundation的巨集顯示的告訴編譯器你們之間的語義關係。
__bridge 轉換objective c和core foundation之間的指標,不轉移擁有關係。
__bridge_retained 或者cfbridgingretain轉換乙個objective c指標到core foundation 指標並且轉移擁有關係。你需要自己釋放物件的關係。
__bridge_transfer 或者cfbridgingrelease將乙個非objective指標轉換為objective c的指標並且轉移關係到arc,不需要自己釋放物件的關係
比如:以前的**
- (void
)logfirstnameofperson:(abrecordref)person
在arc中轉化為以下**。
- (void
)logfirstnameofperson:(abrecordref)person
使用生命週期限定符來避免強引用迴圈
典型的是在父子繼承層次中,父類需要引用了子類,子類同時也用到了父類,需要把父類中定義為strong,而子類中定義為weak。其他一些情況就比較難以琢磨,特別是呼叫了block物件。
在mrr中,__block id x 不增加x的引用計數,而在arc中是增加引用計數的。為了在arc中獲得在mrr中同樣的行為,需要使用__unsafe_unretain __block id x;但是這又是危險的且不鼓勵的。更好的選擇是使用__weak 或者設定把__block id的值設定為nil來跳出retain迴圈。
以下**片段闡述了這個觀點。
最原始的**是這樣的。
myviewcontroller
*mycontroller = [[myviewcontroller alloc] init...];
mycontroller.completionhandler = ^(nsinteger result) ; [
self
presentviewcontroller:mycontroller animated:
yescompletion:^];
可以定義為block,並且在block裡面設定為nil
myviewcontroller
* __block
mycontroller = [[myviewcontroller alloc] init...];
mycontroller.completionhandler = ^(nsinteger result) ;
同樣可以定義乙個臨時的weak變數。
myviewcontroller *mycontroller = [[myviewcontroller alloc] init...];
myviewcontroller *
__weak
weakmyviewcontroller = mycontroller;
mycontroller.completionhandler = ^(nsinteger result) ;
對於特殊的引用迴圈,你需要這樣使用。
myviewcontroller *mycontroller = [[myviewcontroller alloc] init...];
myviewcontroller *
__weak
weakmycontroller = mycontroller;
mycontroller.completionhandler = ^(nsinteger result)
else};
IOS基礎之 十一 記憶體管理 ARC
1.set 方法記憶體管理的相關引數 retain release舊值,retain新值 值適用於oc物件 assign 直接賦值 set方法預設,適用於非oc物件型別,即基本資料型別,也包括列舉和結構體 copy release 舊值,copy 新值 nsstring 2.是否生成set方法 re...
iOS非ARC記憶體管理摘要 實踐型
關於ios記憶體管理。在開發過程中,記憶體管理很重要,我簡單說明一下。1.正確用法 uiview v uiview alloc init 分配後引用計數為1 self.view addsubview v 這兒引用計數加1,為2 v release 這兒引用計數為1 最後系統在 self.view的時...
ARC 記憶體管理見解
arc就是自動引用計數,在arc之前,我們都是通過手動管理引用計數的,也就是手動使用release和retain來是引用計數減1或者加1,arc其實還是使用release和retain,只不過系統幫你完成而成。clang語1言擴充套件很有強的類函式巨集,可以使用以下 宣告編譯時支援arc而檔案 不支...