arc of developer part1

46
ARC of a Developer Part.1 111122日火曜日

Upload: junpei-wada

Post on 28-Jun-2015

669 views

Category:

Education


0 download

TRANSCRIPT

Page 1: Arc of developer part1

ARC of a Developer Part.1

11年11月22日火曜日

Page 2: Arc of developer part1

Automatic Referrence Counting

• Objective-Cのための新しい自動メモリ管理

• 生産性の向上 - タイプ数が少ないからね

• メンテナンス性の向上 - retain、releaseを考えなくても良くなるからね

• 安全で安定 - weak修飾子で安全なweak referrenceができるからね

11年11月22日火曜日

Page 3: Arc of developer part1

メモリ管理、マジ大変

• 手動でメモリを管理するのは熟練が必要

• すでに死んだオブジェクトへのアクセス

• EXC_BAD_ACCESS ヒャッハー!

• 2重にreleaseしちゃう

• NSZombie最高

• 循環参照でリーク

• 宙ぶらりんになったポインタ

11年11月22日火曜日

Page 4: Arc of developer part1

ARCはパフォーマンスを改善する

• GCじゃないから、オブジェクトグラフをスキャンする必要はない

• パフォーマンス

• retain/releaseが2.5倍速くなる

• autoreleasepoolが6倍速くなる

• objc_msgSendが33%速くなる

11年11月22日火曜日

Page 5: Arc of developer part1

ARCを有効にするには?

• 新しいプロジェクトを作るなら

11年11月22日火曜日

Page 6: Arc of developer part1

ARCを有効にするには?

• 既存のプロジェクトをARCにマイグレーションするなら

• LLVM3.0を使用する

• コンパイラオプション 「-fobjc-arc」を指定する

11年11月22日火曜日

Page 7: Arc of developer part1

ファイルごとに無効にするには?

• ファイルごとに、「-fno-objc-arc」を指定する

11年11月22日火曜日

Page 8: Arc of developer part1

実行環境の制約

• iOS4ではweak referenceは使えない

• __unsafe_unretained を使う

• weak reference以外は動くよ!

11年11月22日火曜日

Page 9: Arc of developer part1

所有修飾子

• __strong

• __weak

• __unsafe_unretained

• __autoreleasing

• こんだけ増えるよ!

11年11月22日火曜日

Page 10: Arc of developer part1

Before ARC

• 参照カウント

• 戻り値はautorelease

• 手動でメモリの管理をする

11年11月22日火曜日

Page 11: Arc of developer part1

参照カウント方式のメモリ管理

• オブジェクトをいつ破棄するか管理する一つの手法

• VB6

• COM

• Objective-C

• スマートポインタ

• JAVA、.NETはガベージコレクション Obj-CでもGCあるよ

11年11月22日火曜日

Page 12: Arc of developer part1

参照カウント方式、どういう仕組?

• NSObject *obj = [[NSObject alloc]init];

NSObject

1

* obj

11年11月22日火曜日

Page 13: Arc of developer part1

参照カウント方式、どういう仕組?

• NSObject *obj = [[NSObject alloc]init];

• NSObject *obj2 = [obj retain];

NSObject

2

* obj

* obj2

11年11月22日火曜日

Page 14: Arc of developer part1

参照カウント方式、どういう仕組?

• NSObject *obj = [[NSObject alloc]init];

• NSObject *obj2 = [obj retain];

• [obj release];

NSObject

1* obj2

11年11月22日火曜日

Page 15: Arc of developer part1

参照カウント方式、どういう仕組?

• NSObject *obj = [[NSObject alloc]init];

• NSObject *obj2 = [obj retain];

• [obj release];

• [obj2 release]; NSObject

0破棄!

11年11月22日火曜日

Page 16: Arc of developer part1

Autorelease

• 主にメソッドの戻り値で使う

+(id)array{ NSMutableArray *array = [[[NSMutableArray alloc]init]autorelease]; return array;}

* array

NSArray

1

11年11月22日火曜日

Page 17: Arc of developer part1

Autorelease

• 主にメソッドの戻り値で使う

+(id)array{ NSMutableArray *array = [[[NSMutableArray alloc]init]autorelease]; return array;}

* array

NSArray

1autorelease pool

あとでreleaseしとくわ

11年11月22日火曜日

Page 18: Arc of developer part1

Autorelease

• 主にメソッドの戻り値で使う

+(id)array{ NSMutableArray *array = [[[NSMutableArray alloc]init]autorelease]; return array;}

NSArray

1あとでreleaseしとくわautorelease pool

11年11月22日火曜日

Page 19: Arc of developer part1

Autorelease

• 主にメソッドの戻り値で使う

+(id)array{ NSMutableArray *array = [[[NSMutableArray alloc]init]autorelease]; return array;}

NSArray

0破棄!

11年11月22日火曜日

Page 20: Arc of developer part1

Retain Release Autorerelease

• ちゃんと寿命をわかってかかないといかん

• ちょっとしたミスで致命的なバグを作り込む

11年11月22日火曜日

Page 21: Arc of developer part1

リークしてる?

11年11月22日火曜日

Page 22: Arc of developer part1

リークする

• 相当に注意深くないとリークする

• リークが実用的な範囲に収まってればいいけどね

11年11月22日火曜日

Page 23: Arc of developer part1

Xcode Static Analyzer

• XcodeからAnalyze

• 静的にある程度リークや不正なポインタがないか調べてくれる

11年11月22日火曜日

Page 24: Arc of developer part1

そこでARC

• わりと寿命を意識しなくてもよくなる

• じぶんでRetainとかReleaseとか書かない

11年11月22日火曜日

Page 25: Arc of developer part1

所有修飾子

• __strong

• __weak

• __unsafe_unretained

• __autoreleasing

11年11月22日火曜日

Page 26: Arc of developer part1

nilで初期化されるよ

• 修飾子がついた変数はnilで初期化されるので安全!

• id __strong obj1;

• id __strong obj1 = nil;

11年11月22日火曜日

Page 27: Arc of developer part1

__strong

• そのポインタがオブジェクトを所有するときに使う

• id型とオブジェクト型にデフォルトで付与される

• id test = [[NSObject alloc]init];

• id __strong test = [[NSObject alloc]init];

• もうretain releaseは各必要がないよ

• ポインタを見たらたいていはstrongだと思え!

11年11月22日火曜日

Page 28: Arc of developer part1

__strong

• deallocでのreleaseは必要なくなる

• 自動的にインスタンス変数は破棄されるので、releaseはいらない

• ポインタにオブジェクトを代入すると自動でRetainするイメージ

• スコープが終わると自動でReleaseされるイメージ

11年11月22日火曜日

Page 29: Arc of developer part1

__strong

• arrayにオブジェクトが代入されたら+1されてる

• スコープを抜けたらarrayは破棄されるので、-1されて 破棄される

{ NSMutableArray *array = [[NSMutableArray alloc]init]; [array addObject:[[NSObject alloc]init]]; [array addObject:[[NSObject alloc]init]]; [array addObject:[[NSObject alloc]init]]; [array addObject:[[NSObject alloc]init]];}

これは + 1されない!ここで+1

11年11月22日火曜日

Page 30: Arc of developer part1

従来のRetainのプロパティに近い

@property (nonatomic,retain) NSMutableArray *array;

{ self.array = [[[NSMutableArray alloc]init]autorelease]; [array addObject:[[[NSObject alloc]init]autorelease]]; [array addObject:[[[NSObject alloc]init]autorelease]]; [array addObject:[[[NSObject alloc]init]autorelease]]; [array addObject:[[[NSObject alloc]init]autorelease]];}

{ NSMutableArray *array = [[NSMutableArray alloc]init]; [array addObject:[[NSObject alloc]init]]; [array addObject:[[NSObject alloc]init]]; [array addObject:[[NSObject alloc]init]]; [array addObject:[[NSObject alloc]init]];}

11年11月22日火曜日

Page 31: Arc of developer part1

違うのは実際にはAutoreleaseプールに入らない

• Relaseが呼び出される回数が違う

{ NSMutableArray *array = [[NSMutableArray alloc]init]; [array addObject:[[NSObject alloc]init]]; [array addObject:[[NSObject alloc]init]]; [array addObject:[[NSObject alloc]init]]; [array addObject:[[NSObject alloc]init]];}

これは + 1されない!ここで+1

11年11月22日火曜日

Page 32: Arc of developer part1

戻り値はどうすんの?

• 今まではautoreleaseして返してた

• これからはコンパイラが戻り値かどうかを判定して自動的にautorelease poolに突っ込んでくれます

+(id)array{ id obj = [[NSMutableArray alloc]init]; return obj;}

11年11月22日火曜日

Page 33: Arc of developer part1

プロパティはどうかな?

assign __unsafe_unretained

copy __strong

retain __strong

strong __strong

unsafe_unretained __unsafe_unretained

weak __weak

11年11月22日火曜日

Page 34: Arc of developer part1

strong最高じゃん!

• もうreleaseもretainもいらない!

• というか、コンパイルエラーになるからね

11年11月22日火曜日

Page 35: Arc of developer part1

いやそうでもない

循環参照

11年11月22日火曜日

Page 36: Arc of developer part1

循環参照って?

• パッと見ではわからないリーク

A

B C

DE

11年11月22日火曜日

Page 37: Arc of developer part1

循環参照って?

A

B C

DE

11年11月22日火曜日

Page 38: Arc of developer part1

循環参照

A

B C

DEassign

11年11月22日火曜日

Page 39: Arc of developer part1

どんなコードで循環参照が起こるか@interface Test : NSObject{ id childObject;}-(void)setObject:(id)child;

@end

{ id test1 = [[Test alloc]init]; id test2 = [[Test alloc]init]; [test1 setObject:test2]; [test2 setObject:test1];}

11年11月22日火曜日

Page 40: Arc of developer part1

適当な図で書くと・・・

test1 test2

test1 test2

{ id test1 = [[Test alloc]init]; id test2 = [[Test alloc]init]; [test1 setObject:test2]; [test2 setObject:test1];}

11年11月22日火曜日

Page 41: Arc of developer part1

__weak

@interface Test : NSObject{ id __weak childObject;}-(void)setObject:(id)child;

@end

test1 test2

• Retainされないポインタだと思ったらいい

11年11月22日火曜日

Page 42: Arc of developer part1

__weakのとても素晴らしい機能

• 参照先のオブジェクトが破棄されると自動的にnilが代入される

• 死んだオブジェクトへの参照が発生しない

test1 test2

11年11月22日火曜日

Page 43: Arc of developer part1

__weak

• 循環参照になるときとか、delegateみたいに所有しないものにつける?

id __weak obj = [[NSObject alloc]init];

これは + 1されない!

11年11月22日火曜日

Page 44: Arc of developer part1

autorelease pool

• 短い時間使うオブジェクトをさっくりと破棄する場合

• 自分で新しいThreadを起動した場合

• LLVM3.0以降ならARC無効でも使えるよ

NSAutoreleasePool *pool = [[NSAutoreleasePool alloc]init]; // ほにゃほにゃ [pool drain];

@autoreleasepool { // ほにゃほにゃ }

11年11月22日火曜日

Page 45: Arc of developer part1

トールフリーブリッジ

• ひぃ!

11年11月22日火曜日

Page 46: Arc of developer part1

ナイス書籍

達人出版会で買えるよ

11年11月22日火曜日