objective-c 語法快速過(7)編譯器特性ARC

ARC(是編譯器特性)java

  • ARC是自iOS 5以後增長的新特性,徹底消除了手動管理內存的煩瑣,編譯器會自動在適當的地方插入適當的retain、release、autorelease語句。你再也不須要擔憂內存管理,由於編譯器爲你處理了一切
  • ARC 是編譯器特性,而不是 iOS 運行時特性,它也不是相似於其它語言中的垃圾收集器。所以 ARC 和手動內存管理性能是同樣的,有時還能更加快速,由於編譯器還能夠執行某些優化

ARC基本原理(不是相似 java 的垃圾回收機制)

ARC 的規則很是簡單:只要還有一個強指針變量指向對象,對象就會保持在內存中

強指針和弱指針xcode

  • 默認全部實例變量和局部變量都是Strong指針
  • 弱指針指向的對象被回收後,弱指針會自動變爲nil指針,不會引起野指針錯誤

ARC的判斷準則:只要沒有強指針指向對象,就會釋放對象,弱指針不會這樣,及時有弱指針指向對象,對象沒有強指針指向,也會自動釋放掉。通常,無需顯式聲明爲強指針,可是在封裝裏,定義方法的時候須要寫明。而弱指針,必須顯式說明。默認是強指針。框架

ARC特色函數

 1> 不容許調用release、retain、retainCount佈局

 2> 容許重寫dealloc,可是不容許調用[super dealloc]性能

 3> @property的參數優化

  * strong :成員變量是強指針(適用於OC對象類型)ui

  * weak :成員變量是弱指針(適用於OC對象類型)atom

  * assign : 適用於非OC對象類型spa

 4> 之前的retain改成用strong

oc的指針分2種:

 1> 強指針:默認狀況下,全部的指針都是強指針 __strong

 2> 弱指針:__weak

/*文件名:Dog.h */
#import <Foundation/Foundation.h>
@interface Dog : NSObject
@end

/*文件名:Dog.m */
#import "Dog.h"

@implementation Dog
- (void)dealloc
{
    NSLog(@"Dog is dealloc");
}
@end

/*文件名:Person.h */
#import <Foundation/Foundation.h>
@class Dog;
@interface Person : NSObject
@property (nonatomic, strong) Dog *dog;
@property (nonatomic, strong) NSString *name;
@property (nonatomic, assign) int age;
@end

/*文件名:Person.m */
#import "Person.h"
@implementation Person

- (void)dealloc
{
    NSLog(@"Person is dealloc");
    // [super dealloc];不能寫,不然報錯
}

@end

//  main.m
#import <Foundation/Foundation.h>
#import "Person.h"
#import "Dog.h"

int main()
{
    Dog *d = [[Dog alloc] init];
    Person *p = [[Person alloc] init];
    p.dog = d;
    
    d = nil;
    NSLog(@"%@", p.dog);
    
    return 0;
}

void test()
{
    // 錯誤寫法(沒有意義的寫法)
    __weak Person *p = [[Person alloc] init];
    NSLog(@"%@", p);
    NSLog(@"------------");
}

重構舊代碼(手動內存管理重構爲 ARC 方式)xcode6

這樣操做以後,能夠把非 ARC 項目,轉換爲 ARC 項目。

如何查看項目是不是 ARC?

在 build settings 裏搜索 auto,看選項:

如何使得 ARC 和非 ARC 在一個項目共存?

常常須要使用第三方框架,或者一些其餘的舊代碼,那麼有支持 ARC 的,也有不支持的,怎麼辦呢?能夠這樣設置:在編譯選項裏

雙擊須要非 ARC的文件,以下設置:

-fno-objc-arc

這樣這個文件就能使用 retain ,release,autorelease等關鍵字

-f 表明 flags 標記的意思,固定寫法。

 

反過來,對於非 ARC 項目,這樣設置:

-f-objc-arc

ARC使用注意

  • 不能調用release、retain、autorelease、retainCount
  • 能夠重寫dealloc,可是不能調用[super dealloc]
  • @property : 想長期擁有某個對象,應該用strong,其餘對象用weak
  • 其餘基本數據類型依然用assign
  • 兩端互相引用時,一端用strong、一端用weak

一樣,在 ARC 項目裏,也有循環雙端引用的現象,你 strong 我,我 strong 你的狀況。解決辦法照舊。兩端互相引用時,一端用strong、一端用weak

/*文件名:Dog.h */
#import <Foundation/Foundation.h>
@class Person;

@interface Dog : NSObject
@property (nonatomic, weak) Person *person;
@end

/*文件名:Dog.m */
#import "Dog.h"
@implementation Dog
- (void)dealloc
{
    NSLog(@"Dog--dealloc");
}
@end

/*文件名:Person.h */
#import <Foundation/Foundation.h>
@class Dog;

@interface Person : NSObject
@property (nonatomic, strong) Dog *dog;
@end

/*文件名:Person.m */

#import "Person.h"

@implementation Person
- (void)dealloc
{
    NSLog(@"Person--dealloc");
}
@end

//  main.m
#import <Foundation/Foundation.h>
#import "Person.h"
#import "Dog.h"
/*
 當兩端循環引用的時候,解決方案:
 1> ARC
 1端用strong,另1端用weak
 
 2> 非ARC
 1端用retain,另1端用assign
 */
int main()
{
    Person *p = [[Person alloc] init];
    Dog *d = [[Dog alloc] init];
    p.dog = d;
    d.person = p;

    return 0;
}

不然,一樣是報錯,好比都使用 strong 屬性

 Person *p = [[Person alloc] init];    
    Dog *d = [[Dog alloc] init];

內存佈局:

p.dog = d;//把dog對象賦值給 person 對象裏的_dog,指針,是個強指針。

d.person = p;//一樣,dog 對象裏的_person 強指針指向了 person 對象

當程序執行完畢,或者說 main 函數執行完畢,自動變量銷燬

由於都是強指針,發生如上狀況,內存泄露。故__weak 或者 weak 屬性通常用在循環引用的場合,其餘場合很少見。

相關文章
相關標籤/搜索