iOSåãã®å€åœã®éçºè ã®ããã°ãèšäºãé·ãéèªãã§ããŸãã å æ¥ã ãã€ã¯ã»ã¢ãã·ã¥ãšããéçºè ããã®èªååç §ã«ãŠã³ãã«é¢ãã奜å¥å¿ãçã§ããªã詳现ãªèšäºã«åºäŒããŸããã
ãã®èšäºã¯éåžžã«å€§ãããããç§ãäœæãã翻蚳ãããã€ãã®éšåã«åå²ãããªã¹ã¯ããããŸãã ç§ã¯2ã€ã®éšåã§ç¶æããããšèããŠããŸãã
Appleããã®é©æ°ãçºè¡šããŠä»¥æ¥ãèªè ã¯èªååç §ã«ãŠã³ãïŒARCïŒã¡ã«ããºã ã«ã€ããŠæžãããšãç§ã«å§ããŠããŸããã æãæ¥ãŸããã æ¬æ¥ã¯ãAppleã®æ°ããã¡ã¢ãªç®¡çã·ã¹ãã ã«ã€ããŠèª¬æããŸãããããã©ã®ããã«æ©èœããã®ãããããèªåã§æ©èœãããæ¹æ³ã§ãã
ã³ã³ã»ãã
Clang Static Analyzerã¯ãã³ãŒãå ã®ã¡ã¢ãªç®¡çãšã©ãŒãèŠã€ããã®ã«éåžžã«äŸ¿å©ãªããŒã«ã§ãã ããªããšç§ã䌌ãŠããå Žåãã¢ãã©ã€ã¶ãŒã®åºåãèŠãŠããã¢ãã©ã€ã¶ãŒããšã©ãŒãæ€åºããå Žåããªãç§ã§ã¯ãªãä¿®æ£ãã¹ãã§ã¯ãªããããšèããŸãã
èŠããã«-ããã¯ARCã®æ¬è³ªã§ãã ã¡ã¢ãªç®¡çã«ãŒã«ã¯ã³ã³ãã€ã©ã«çµã¿èŸŒãŸããŠããŸãã ããããéçºè ããšã©ãŒãèŠã€ããã®ãå©ããããã«ãããã䜿çšãã代ããã«ãARCã¡ã«ããºã ã¯åã«å¿ èŠãªåŒã³åºããæ¿å ¥ããŸãã ãããŠããã ãã§ãã
ARCã¡ã«ããºã ã¯ãã¬ããŒãžã³ã¬ã¯ã¿ãŒãšæåã¡ã¢ãªç®¡çã®éã®ã©ããã«ãããŸãã ã¬ããŒãžã³ã¬ã¯ã¿ãŒãšåæ§ã«ãARCã¯éçºè ãretain / release / autoreleaseåŒã³åºããèšè¿°ããå¿ èŠããªãããŸã ã ãã ããã¬ããŒãžã³ã¬ã¯ã¿ãšã¯ç°ãªããARCã¯ã«ãŒããä¿æããããã«ãããªãæ¹æ³ã§ãåå¿ããŸããã çžäºã«åŒ·ããªã³ã¯ãæã€2ã€ã®ãªããžã§ã¯ãã¯ã誰ãåç §ããŠããªãå Žåã§ããARCã«ãã£ãŠåŠçãããããšã¯ãããŸããã ARCã¯ã»ãšãã©ã®ã¡ã¢ãªç®¡çã¿ã¹ã¯ããããã°ã©ãã解æŸããŸãããéçºè ã¯ãªããžã§ã¯ããžã®å³å¯ãªåŸªç°åç §ãåé¿ãŸãã¯æåã§ç Žæ£ããå¿ èŠããããŸãã
å®è£ ã®è©³çŽ°ã«é¢ããŠã¯ãARCãšAppleã®GCå®è£ ã®ââãã1ã€ã®éèŠãªéãã¯ãARCã¯æ¹åãããŠããªããšããããšã§ãã Appleã®GCã䜿çšããå Žåãã¢ããªã±ãŒã·ã§ã³å šäœãGCç°å¢ã§å®è¡ããããã©ããã®ããããã§ãã ã€ãŸãã䜿çšããAppleãã¬ãŒã ã¯ãŒã¯ããµãŒãããŒãã£ã©ã€ãã©ãªãå«ããã¢ããªã±ãŒã·ã§ã³å ã®ãã¹ãŠã®Objective-Cã³ãŒãã¯ã䜿çšããããã«GCãšäºææ§ãããå¿ èŠããããŸãã ARCãåãã¢ããªã±ãŒã·ã§ã³å ã§æåã®ã¡ã¢ãªç®¡çãšãšãã«ãéARCãã³ãŒããšå¹³åçã«å ±åããããšã¯æ³šç®ã«å€ããŸãã ããã«ãããGCãå°å ¥ããããšãã«ééãã倧ããªäºææ§ãšä¿¡é Œæ§ã®åé¡ãªãã«ããããžã§ã¯ããéšåçã«å€æã§ããŸãã
Xcode
ARCã¯ãXcode 4.2ããŒã¿çãããClangïŒå¥åãApple LLVMã³ã³ãã€ã©ãïŒã䜿çšããã³ã³ãã€ã«ãéžæããå Žåã«ã®ã¿å©çšã§ããŸãã 䜿çšããã«ã¯ããObjective-C Automatic Reference Countingããšããããããããååã®èšå®ã«æ³šæããã ãã§ååã§ãã
æ¢ã«æ¢åã®ã³ãŒãããŒã¹ã§äœæ¥ããŠããå Žåããã®èšå®ãå€æŽãããšãèšå€§ãªæ°ã®ãšã©ãŒãçºçããå¯èœæ§ããããŸãã ARCã¯ãããªãã®å Žæã®ã¡ã¢ãªã管çããã ãã§ãªããèªåã§ã¡ã¢ãªã管çããããšãçŠæ¢ããŠããŸãã ARCã䜿çšãããšã retain / release / autoreleaseã¡ãã»ãŒãžããªããžã§ã¯ãã«éä¿¡ããããšã¯ãŸã£ããåãå ¥ããããŸããã Cocoaã¯ãã®ãããªã¡ãã»ãŒãžã§ãã£ã±ãã§ãããšããäºå®ã«åºã¥ããŠãå¿ ç¶çã«å€§éã®ãšã©ãŒãçºçããŸãã
幞ããªããšã«ãXcodeã¯æ¢åã®ã³ãŒããå€æããããŒã«ãæäŸããŸãã ãããè¡ãã«ã¯ã[ ç·šé]-> [ãªãã¡ã¯ã¿ãªã³ã°...]-> [Objective-C ARCã«å€æ...]ãéžæããŸããXcodeã䜿çšãããšãã³ãŒãã段éçã«å€æã§ããŸãã äœããã¹ãããæå®ããå¿ èŠãããéåžžã«ããã«ããã¯ãé€ããšããã®ããã»ã¹ã¯ã»ãšãã©èªåçã«è¡ãããŸãã
åºæ¬æ©èœ
Cocoaã®ã¡ã¢ãªç®¡çã«ãŒã«ã¯éåžžã«ç°¡åã§ãã èŠããã«ïŒ
1. allocãnewãcopy ã retainããªããžã§ã¯ãã«éä¿¡ããå Žåã releaseãŸãã¯autoreleaseã䜿çšããŠãããè£æ£ããå¿ èŠããããŸãã
2.æ¡é 1ã§èª¬æããæ¹æ³ãšã¯ç°ãªãæ¹æ³ã§ãªããžã§ã¯ããåãåãããªããžã§ã¯ããååã«é·ãæéãçãããç¶æ ã«ããå¿ èŠãããå Žåã¯ã retainãŸãã¯copyã䜿çšããå¿ èŠããããŸã ã åœç¶ãããã¯åŸã§è£åããå¿ èŠããããŸãã
ãããïŒã«ãŒã«ïŒã¯ãããã»ã¹ã®èªååã«å€§ããè²¢ç®ããŸãã ããªããæžãå ŽåïŒ
Foo *foo = [[Foo alloc] init]; [foo something]; return;
ã³ã³ãã€ã©ãŒã¯ãäžåè¡¡ãªallocãæ€åºãã以äžã«å€æããŸãã
Foo *foo = [[Foo alloc] init]; [foo something]; [foo release]; return;
å®éã«ã¯ãã³ã³ãã€ã©ã¯ãªãªãŒã¹ã¡ãã»ãŒãžããªããžã§ã¯ãã«éä¿¡ããããã®ã³ãŒããæ¿å ¥ããŸããã 代ããã«ãç¹å¥ãªã©ã³ã¿ã€ã é¢æ°ãžã®åŒã³åºããæ¿å ¥ããŸãã
Foo *foo = [[Foo alloc] init]; [foo something]; objc_release(foo); return;
ããã§ãããã€ãã®æé©åãé©çšã§ããŸãã - ãªãªãŒã¹ãåå®çŸ©ãããŠããªãå Žåãã»ãšãã©ã®å Žåã objc_releaseã¯Objective-Cã¡ãã»ãŒãžã¡ã«ããºã ããã€ãã¹ã§ããé床ããããã«åäžããŸãã
ãã®ãããªèªååã¯ãã³ãŒããããå®å šã«ããã®ã«åœ¹ç«ã¡ãŸãã å€ãã®Cocoaéçºè ã¯ããéåžžã«é·ãéããšããçšèªãæ¡é 2ãã解éããŠããŸããããã¯ãã€ã³ã¹ã¿ã³ã¹å€æ°ãŸãã¯åæ§ã®å Žæã«æ ŒçŽãããŠãããªããžã§ã¯ããæå³ããŸãã éåžžãããŒã«ã«ã®äžæãªããžã§ã¯ãã«ä¿æãšè§£æŸãé©çšããŸããã
Foo *foo = [self foo]; [foo bar]; [foo baz]; [foo quux];
ãã ãã次ã®æ§æã¯éåžžã«å±éºã§ãã
Foo *foo = [self foo]; [foo bar]; [foo baz]; [self setFoo: newFoo]; [foo quux]; // crash
ããã¯ãå€ãè¿ããããŸã§retain / autoreleaseãéä¿¡ããã-fooã®ã²ãã¿ãŒãæã€ããšã§ä¿®æ£ã§ããŸãã ããã¯æå¹ãªãªãã·ã§ã³ã§ãããã¡ã¢ãªãç©æ¥µçã«äœ¿çšããå€ãã®äžæãªããžã§ã¯ããçæã§ããŸãã ãã ããARCã¯ããã«äœåãªåŒã³åºããåå·çã«æ¿å ¥ããŸãã
Foo *foo = objc_retainAutoreleasedReturnValue([self foo]); [foo bar]; [foo baz]; [self setFoo: newFoo]; [foo quux]; // fine objc_release(foo);
ããã«ãåçŽãªã²ãã¿ãŒãäœæããå Žåã§ããARCã¯ãããå¯èœãªéãå®å šã«ããŸãã
- (Foo *)foo { return objc_retainAutoreleaseReturnValue(_foo); }
ãã ããããã¯äžæãªããžã§ã¯ãã®éå°ãªæ°ã®åé¡ãå®å šã«ã¯è§£æ±ºããŸããïŒ åãšåãããã«ãã²ãã¿ãŒã§ã¯retain / autoreleaseã®çµã¿åããã䜿çšããåŒã³åºãã³ãŒãã§ã¯retain / releaseã®çµã¿åããã䜿çšããŸãã ããã¯ééããªãç¡å¹ã§ãïŒ
ãããã枬å®ããã«å¿é ããªãã§ãã ããã åè¿°ã®ããã«ãARCïŒæé©åã®ããïŒã¯ãã¡ãã»ãŒãžãéä¿¡ããã ãã§ãªããç¹å¥ãªåŒã³åºãã䜿çšããŸãã retainãšreleaseãå éããããšã«å ããŠããããã®åŒã³åºãã¯äžè¬çã«ããã€ãã®æäœãæé€ããŸãã
objc_retainAutoreleaseReturnValueã®å®è¡äžãã¹ã¿ãã¯ãç£èŠããåŒã³åºãå ã®æ»ãã¢ãã¬ã¹ãèšæ¶ããŸãã ããã«ããã圌ã¯å®äºåŸã«äœãèµ·ããããæ£ç¢ºã«ç¥ãããšãã§ããŸãã ã³ã³ãã€ã«ã®æé©åããªã³ã«ããŠã objc_retainAutoreleaseReturnValueãåŒã³åºãããšãã æ«å°ŸåŒã³åºãã®æé©åã®çç±ã«ãªãå ŽåããããŸãã
Rantimeã¯ããã®è¿ä¿¡ã¢ãã¬ã¹ã®ã¯ã¬ã€ãžãŒãªãã§ãã¯ã䜿çšããŠãäžå¿ èŠãªäœæ¥ãåé¿ããŸãã ããã«ããã èªå解æŸã®éä¿¡ãäžèŠã«ãªããä¿æã¡ãã»ãŒãžãç Žæ£ããããã«åŒã³åºãå ã«éç¥ãããã©ã°ãèšå®ãããŸãã å šäœã®æ§é ã¯ãã²ãã¿ãŒã§åäžã®ãªãã€ã³ã䜿çšããåŒã³åºãã³ãŒãã§åäžã®ãªãªãŒã¹ã䜿çšããŸããããã¯ãããå®å šã§å¹ççãªã¢ãããŒãã§ãã
泚ïŒãã®æé©åã¯ãARCã¡ã«ããºã ã䜿çšããªãã³ãŒããšå®å šã«äºææ§ããããŸãã
ã²ãã¿ãŒãARCã䜿çšããªãã€ãã³ãã§ã¯ãäžèšã®ãã©ã°ã¯èšå®ããããåŒã³åºãåŽã¯ä¿æ/解æŸã¡ãã»ãŒãžã®å®å šãªçµã¿åããã䜿çšã§ããŸãã
ã²ãã¿ãŒãARCã䜿çšããããåŒã³åºãå ã¯äœ¿çšããªãã€ãã³ãã§ã¯ãã²ãã¿ãŒã¯ç¹å¥ãªã©ã³ã¿ã€ã é¢æ°ãããã«åŒã³åºãã³ãŒãã«æ»ããªãããšãèªèããŠããããã ä¿æ/èªå解æŸã¡ãã»ãŒãžã®å®å šãªçµã¿åããã䜿çšã§ããŸãã
äžéšã®ããã©ãŒãã³ã¹ã¯å€±ãããŸãããã³ãŒãã¯å®å šã«æ£ãããŸãŸã§ãã
ããã«ãARCãšã³ãžã³ã¯ããã¹ãŠã®ã¯ã©ã¹ã®-deallocã¡ãœãããèªåçã«äœæãŸãã¯å ¥åããŠããã¹ãŠã®ã€ã³ã¹ã¿ã³ã¹å€æ°ã解æŸããŸãã åæã«ã -deallocãæåã§èšè¿°ããå¯èœæ§ã¯ãŸã ãããŸããïŒããã¯å€éšãªãœãŒã¹ã管çããã¯ã©ã¹ã«å¿ èŠã§ãïŒãå°æ¥çã«ã¯ã¯ã©ã¹ã€ã³ã¹ã¿ã³ã¹å€æ°ãæåã§è§£æŸããå¿ èŠã¯ãããŸããã ARCã¯æåŸã«[super dealloc]åŒã³åºããæ¿å ¥ããã®ã§ãå¿é ããå¿ èŠããããŸããã
èšãããããšã説æããŸãã
以åã¯ã次ã®æ§æã䜿çšã§ããŸããã
- (void)dealloc { [ivar1 release]; [ivar2 release]; free(buffer); [super dealloc]; }
ããããããªãã¯æžãã ãã§ãïŒ
- (void)dealloc { free(buffer); }
-deallocã¡ãœãããã€ã³ã¹ã¿ã³ã¹å€æ°ã解æŸããã ãã®å Žåããã®æ§æïŒARCã䜿çšïŒã¯åãããšãè¡ããŸãã
ã«ãŒããšåŒ±ããªã³ã¯
ARCã§ã¯ãéçºè ã埪ç°ãªã³ã¯ãæåã§åŠçããå¿ èŠããããŸãããã®åé¡ã解決ããæåã®æ¹æ³ã¯ã匱ããªã³ã¯ã䜿çšããããšã§ãã
ARCã¯ãã«ã®åŒ±ããªã³ã¯ã䜿çšããŸãã ãã®ãããªãªã³ã¯ã¯ãåç §å ã®ãªããžã§ã¯ãããã©ã€ããã«ä¿ã€ã ãã§ãªããåç §å ã®ãªããžã§ã¯ããç Žæ£ããããšèªåçã«nilã«ãªããŸãã 匱ããªã³ã¯ããŒãã«ããããšã§ãããããã€ã³ã¿ãŒã®åé¡ãé¢é£ããã¯ã©ãã·ã¥ãããã³ã¢ããªã±ãŒã·ã§ã³ã®äºæããªãåäœããªããªããŸãã
ãã«å¯èœãªåŒ±ããªã³ã¯ãäœæããã«ã¯ã宣èšæã«__weakãã¬ãã£ãã¯ã¹ãè¿œå ããã ãã§ãã
ããšãã°ããã®ã¿ã€ãã®ã€ã³ã¹ã¿ã³ã¹å€æ°ã®äœæã¯æ¬¡ã®ãšããã§ãã
@interface Foo : NSObject { __weak Bar *_weakBar; }
ããŒã«ã«å€æ°ã¯åãæ¹æ³ã§äœæãããŸãïŒ
__weak Foo *_weakFoo = [object foo];
åŸã§éåžžã®å€æ°ãšããŠäœ¿çšã§ããŸãããå¿ èŠã«å¿ããŠå€ã¯èªåçã«nilã«ãªããŸãã
[_weakBar doSomethingIfStillAlive];
ãã ãã __ weakå€æ°ã¯ã»ãšãã©ãã¹ãŠã®æç¹ã§nilã«ãªãå¯èœæ§ãããããšã«æ³šæããŠãã ãã ã
ã¡ã¢ãªç®¡çã¯åºæ¬çã«ãã«ãã¹ã¬ããããã»ã¹ã§ãããççµåãªããžã§ã¯ãã¯1ã€ã®ã¹ã¬ããã§ç Žæ£ãããå¥ã®ã¹ã¬ããããã®ãªããžã§ã¯ãã«ã¢ã¯ã»ã¹ã§ããŸãã
説æããŸãã
次ã®ã³ãŒãã¯æ£ãããããŸããïŒ
if(_weakBar) [self mustNotBeNil: _weakBar];
代ããã«ãããŒã«ã«ã®åŒ·åãªãªã³ã¯ã䜿çšããŠã次ã確èªããŸãã
Bar *bar = _weakBar; if(bar) [self mustNotBeNil: bar];
ãã®å Žåã ããŒã¯åŒ·ãåç §ã§ããããããªããžã§ã¯ãã䜿çšãããŠããéãã£ãšãªããžã§ã¯ãïŒããã³énilå€æ°ïŒãæå¹ã«ãªããŸãã
ARCã§ã®åŒ±ããªã³ã¯ã®ç¡å¹åã®å®è£ ã«ã¯ãObjective-Cã®åç §ã¢ã«ãŠã³ãã£ã³ã°ã·ã¹ãã ãšåŒ±ããªã³ã¯ã®ç¡å¹åã·ã¹ãã ã®éã®ç·å¯ãªèª¿æŽãå¿ èŠã§ãã ã€ãŸãã retainããã³releaseããªãŒããŒã©ã€ãããã¯ã©ã¹ã¯ãnull蚱容匱åç §ã®ãªããžã§ã¯ãã«ã¯ãªããŸããã ç°åžžã§ã¯ãããŸãããäžéšã®Cocoaã¯ã©ã¹ã¯ããã«èŠããã§ããŸãïŒ NSWindowãªã© ïŒã
幞ããªããšã«ãåæ§ã®ééããç¯ããå Žåãããã°ã©ã ã¯ã次ã®ããã«ãã¯ã©ãã·ã¥ãããšãã«ã¡ãã»ãŒãžãçºè¡ããããšã«ãããããã«ãããç¥ãããŸãã
objc[2478]: cannot form weak reference to instance (0x10360f000) of class NSWindow
åæ§ã®ã¯ã©ã¹ãžã®åŒ±ãåç §ãæ¬åœã«å¿ èŠãªå Žåã¯ã __ weakã®ä»£ããã«__unsafe_unretainedã䜿çšã§ããŸãã ããã«ããããªã»ãããããªã匱ããªã³ã¯ãäœæãããŸãã ãã ãããã€ã³ã¿ãŒãæããŠãããªããžã§ã¯ããç Žæ£ãããåŸã¯ããã®ãã€ã³ã¿ãŒã䜿çšããŠããªãããšã確èªããå¿ èŠããããŸãïŒæåã§ãªã»ããããããšããå§ãããŸãïŒã
泚æããŠãã ããïŒnulläžå¯ã®åŒ±ããªã³ã¯ã䜿çšãããšãç«ã§éã¶ããšãã§ããŸãã
ARCã䜿çšããŠMac OS X 10.6ããã³iOS 4ã®ã¢ããªã±ãŒã·ã§ã³ãäœæããå¯èœæ§ã«ããããããããããã®OSã§ã¯ãã«å¯èœãªãŠã£ãŒã¯ãªã³ã¯ã¯äœ¿çšã§ããŸããïŒç¿»èš³è ã®ã¡ã¢ïŒARC解æã®ã³ã³ããã¹ãã§ãã®æç« ã®æå³ãå®å šã«èª€è§£ããŸãããéãŒãã®åŒ±åç §ã§ãªããã°ãªããŸããïŒã
ãã¹ãŠã®åŒ±ããªã³ã¯ã¯__unsafe_unretainedã§åŠçããå¿ èŠããããŸãã
ãã«å¯èœã®åŒ±ããªã³ã¯ã¯éåžžã«å±éºã§ããããããã®å¶éã«ããããããã®ã·ã¹ãã ã§ARCã䜿çšããé åãå€§å¹ ã«äœäžããŸãã
ããã¹ããããªã倧ãããªã£ãã®ã§ãããã§ç¿»èš³ã®æåã®éšåãçµäºããŸãã ç§ã¯ãããå¯èœãªéããã·ã¢èªã«ç¿»èš³ããããšããŸããããèªãŸããè³æã®99ïŒ ãè±èªã§ããå Žåã¯ç¹ã«ç°¡åã§ã¯ãããŸããã
圌ããèšãããã«ãã楜ãã¿ã«ã