ARC
Automatic Reference Counting
clang 新しいコンパイラ LLVMプロジェクト (http://llvm.org/) のコンパイラ C Objective-C C++ の効率的なコードを生成 オプションなどは gcc とほぼ共通 Apple社独自の拡張機能を実現 ARC ブロックオブジェクトなど ARCを利用するには clang が必須 コンパイルオプションに -fobjc-arc を指定
簡単な例 変数 a にオブジェクト obj を代入 a = obj; コンパイル [obj retain]; [a release]; a = obj; 挿入されるコード objがnilなら省略され るかもしれない 挿入されるコード autoreleaseかもしれない
どんなコードが挿入される 典型的には 変数へオブジェクトを代入すると 古い値が release さ れ 新しい値が retain されるだろう 自動変数 メソッドや関数内の変数 に代入されていたオ ブジェクトは その自動変数のスコープから抜ける際に release されるだろう メソッド または関数 の引数としてオブジェクトを渡す と 渡す直前に retain され メソッドから戻った後で release されるだろう releaseではなく autorelease が使われることもある 最適化が行われ 冗長な操作は削除される 詳細について知る必要はない
id pool = [[NSAutoreleasePool alloc] init]; a = [[[Volume alloc] init] autorelease]; [pool release];
@autoreleasepool { a = [[Volume alloc] init];
deallocの再定義 - (void)dealloc { [view setdelegate: nil]; [view release]; [filepath release]; [super dealloc]; 後始末のコードが必要 なら記述できる ARCでは インスタンス変数は 自動的に解放される ので 記述しない - (void)dealloc { [view setdelegate: nil]; [view release]; [filepath release]; スーパークラスのdealloc [super dealloc]; は自動的に呼び出される ので記述しない
weak NSString *filepath;
- = unsafe_unretained NSString *path;
@property(strong) NSString *path; @property(weak) NSData *cache; @property(assign) NSWindow *window;
@interface Staff : NSObject @property(strong) Staff *boss; @property(readonly) NSString *name; - (id)initwithname:(nsstring *)str; + (Staff *)staffwithname:(nsstring *)str; - (void)dealloc; - (NSString *)description; @end @implementation Staff { NSString *name; @synthesize boss; @synthesize name;
- (id)initwithname:(nsstring *)str { if ((self = [super init])!= nil) { name = str; boss = nil; return self; + (Staff *)staffwithname:(nsstring *)str { return [[self alloc] initwithname:str]; - (void)dealloc { printf(" release: %s\n",[name UTF8String]); - (NSString *)description { return [NSString stringwithformat:@"name:%@(%@)", name, (boss? boss.name : @"--") ]; @end
int main(void) { Staff *a, *b; @autoreleasepool { a = [Staff staffwithname:@"ann"]; @autoreleasepool { b = [Staff staffwithname:@"bill"]; Staff *c = [Staff staffwithname:@"chris"]; a.boss = b; b.boss = c; printf("%s\n", [[a description] UTF8String]); printf("%s\n", [[b description] UTF8String]); printf("%s\n", [[a description] UTF8String]); printf("%s\n", [[b description] UTF8String]); return 0; Name:Ann (Bill) Name:Bill (Chris) Name:Ann (Bill) Name:Bill (Chris) release: Ann release: Bill release: Chris
a b c int main(void) { Staff *a, *b; @autoreleasepool { a = [Staff staffwithname:@"ann"]; @autoreleasepool { b = [Staff staffwithname:@"bill"]; Staff *c = [Staff staffwithname:@"chris"]; a.boss = b; b.boss = c; printf("%s\n", [[a description] UTF8String]); printf("%s\n", [[b description] UTF8String]); printf("%s\n", [[a description] UTF8String]); printf("%s\n", [[b description] UTF8String]); Name:Ann (Bill) return 0; Name:Bill (Chris) release: Chris Name:Ann (Bill) ゼロ化 bossを弱い参照にすると Name:Bill (--) release: Bill release: Ann
int main(void) { Staff *a, *b; @autoreleasepool { a = [Staff staffwithname:@"ann"]; @autoreleasepool { b = [Staff staffwithname:@"bill"]; Staff *c = [Staff staffwithname:@"chris"]; a.boss = b; b.boss = c; c.boss = a; printf("%s\n", [[a description] UTF8String]); printf("%s\n", [[b description] UTF8String]); printf("%s\n", [[a description] UTF8String]); printf("%s\n", [[b description] UTF8String]); return 0; Name:Ann (Bill) Name:Bill (Chris) Name:Ann (Bill) Name:Bill (Chris)
int main(void) { int i; int (^b[4])(void); 3 3 3 3 for (i = 0; i < 4; i++) b[i] = ^{ return i; ; for (i = 0; i < 4; i++) printf(" %d", b[i]()); putchar('\n'); return 0; 0 1 2 3
struct monster { int x, y; UIImage *image; Creature *attr; ;
( autoreleasing NSError **) + (void)makepartners:(staff * strong [])p
strong weak autoreleasing unsafe_unretained bridge bridge_retained bridge_transfer
bridge CFDataRef d =...; NSData *data = ( bridge NSData *) d; NSString *str =...; CFStringRef s = ( bridge CFStringRef) str; NSData *data =...; void *pointer = ( bridge void *) data;
bridge_retained NSString *str =...; CFStringRef s = ( bridge_retained CFStringRef)str; bridge_transfer CFDataRef d =...; NSData *data = ( bridge_transfer NSData *) d;
Interface Builderでの注意事項 カスタムオブジェクト プログラマが付け加えたオ ブジェクト のアウトレットは基本的に弱い参照に するべきとされている トップレベルのオブ ジェクトは相互に強い 参照をしてもよい トップレベルの オブジェクト