ããã«ã¡ã¯ã ç§ã®äžé£ã®èšäºã¯ãCããObjective-Cã«åãæ¿ããããã°ã©ããŒã«æ§ãããããObjective-Cã¯ã©ã®ããã«Cã«åºã¥ããŠããã®ã§ããïŒãããã³ãããã¯ãã¹ãŠå éšããã©ã®ããã«çºçããŸããïŒã
ãæèŠããå¯ãããã ãããããšãããããŸããObjective-Cã©ã³ã¿ã€ã ã®åŸ¹åºçãªç 究ã«é¢ããèšäºãç¶ããããšã¯ãç§ã«ãšã£ãŠã€ã³ã»ã³ãã£ããšãªãããšã瀺ããŠãããããšã«èå³ãæã£ãŠããŸãã ããã€ãã®èª¬æããããã®ã§ããã®ããŒããèšäºã®äž»é¡ããå§ããŸããã
- ç§ã®èšäºã¯Objective-Cã®ããã¥ã¢ã«ã§ã¯ãããŸããããObjective-Cã©ã³ã¿ã€ã ã¯Cèšèªã¬ãã«ã§ç解ã§ããã»ã©äœãç 究ããŠããŸãã
- ç§ã®èšäºã¯ãCèšèªãšãããã¬ãŒã®ã¬ã€ãã§ã¯ãããŸããã Cèšèªã®ã¬ãã«ãŸã§äžéããŸãããããããäœãã¯ãããŸããã ãããã£ãŠãã¡ã¢ãªå ã®ããŒã¿ã®è¡šç€ºãªã©ã®åé¡ã«ã¯è§ŠããŸããã ããªãã¯ç§ãªãã§ããããã¹ãŠç¥ã£ãŠãããšä»®å®ãããŸãã
ãã¡ãããèšäºã¯ä»ã®ã«ããŽãªãŒã®ããã°ã©ããŒã«ãèå³ããããŸãã ãã ããããã2ã€ã®ç¹ã«çæããŠãã ããã
æåã®èšäºãèªãã§ããªãå Žåã¯ããŸãhttp://habrahabr.ru/post/250955/ãèªãããšã匷ããå§ãããŸãã ãããŠããã§ã«èªãã§ãããªããç«ãžããããã
ãã¡ãœãããåŒã³åºãããšãã¡ãã»ãŒãžãéä¿¡ããã
ååã®èšäºã§ã¯ããã¡ãœããåŒã³åºãããŸãã¯ãã¡ãã»ãŒãžã®éä¿¡ããšãåŒã°ããŠããŸããã
[myObj someMethod];
å®è¡æã«ããã®ãããªèšèšã¯æçµçã«objc_msgSendïŒïŒé¢æ°ã®åŒã³åºããšã»ã¬ã¯ã¿ãŒãé©åã«æ±ãããšã«åž°çãããšããçµè«ã«éããŸããã
ããŠãobjc_msgSendïŒïŒé¢æ°ã詳现ã«èª¿ã¹ãŠããã®æªåé«ããªããžã§ã¯ããžã®ã¡ãã»ãŒãžéä¿¡ã®åçãç解ããŸãããã
ãã®é¢æ°ã¯ããªããžã§ã¯ãã®ã¡ãœãããåŒã³åºããã³ã«åŒã³åºãããŸãã äœæ¥ã®é床ãã¢ããªã±ãŒã·ã§ã³å šäœã®é床ã«å€§ãã圱é¿ãããšä»®å®ããã®ã¯è«ççã§ãã ãããã£ãŠããã®é¢æ°ã®ãœãŒã¹ã³ãŒããèŠããšãåãã©ãããã©ãŒã ã®ã¢ã»ã³ããªèšèªã§å®è£ ãããŠããããšãããããŸãã
ãœãŒã¹ã³ãŒããç解ããåã«ã ããã¥ã¡ã³ããç解ããããšããå§ãããŸãã
...
ã¡ãã»ãŒãžéä¿¡æ©èœã¯ãåçãªã³ã¯ã«å¿ èŠãªãã¹ãŠãå®è¡ããŸãã
- ãŸããã»ã¬ã¯ã¿ãåç §ããããã·ãŒãžã£ïŒã¡ãœããå®è£ ïŒãèŠã€ããŸãã åãã¡ãœãããå®å šã«ç°ãªãã¯ã©ã¹ã§å®è£ ã§ãããããããïŒ objc_msgSendé¢æ°ãäœæè ã®ã¡ã¢ ïŒãæ€çŽ¢ãããŸãã«ãã®æé ã¯ãåä¿¡è ã¯ã©ã¹ïŒ ã¡ãã»ãŒãžã®éä¿¡å ãäœæè ã®ã¡ã¢ ïŒã«ãã£ãŠç°ãªããŸã ã
- 次ã«ã圌女ã¯ãã®ããã·ãŒãžã£ãåŒã³åºããåä¿¡è ãªããžã§ã¯ãïŒãªããžã§ã¯ããžã®ãã€ã³ã¿ïŒãšã¡ãœããåŒã³åºãã§æž¡ããããã¹ãŠã®åŒæ°ãæž¡ããŸãã
- æåŸã«ãããã·ãŒãžã£ã®çµæãç¬èªã®çµæãšããŠè¿ããŸãã
...
åæ
çãªäœè«
ãã§ã«ããã¥ã¡ã³ãã ãã«åºã¥ããŠãObjective Cèšèªã«é©çšããå Žåããã¡ãœãããåŒã³åºãããšãããã¬ãŒãºã¯çµ¶å¯Ÿã«æ£ããããšãç解ããŠããŸãããããã£ãŠãè³¢æãªäººãããªããä¿®æ£ãããšããã¡ãœãããåŒã³åºããã§ã¯ãªããããç¥ãããŠãã2ã€ã®åèª-ããã¥ã¡ã³ããèªã-ã«éã£ãŠãã ããã
ããŠã2çªç®ãš3çªç®ã®æ®µèœã§ã¯ããã¹ãŠãéåžžã«æ確ã§ãã ããããæåã®ãã®ã¯ããå°ã詳现ã«æ±ãå¿ èŠããããŸããå®å šã«æœè±¡çãªã»ã¬ã¯ã¿ãŒãããã«æ£ç¢ºã«éåžžã«ç¹å®ã®é¢æ°ã«å€æããããã§ãã
Cã®ã¯ã©ã¹ã¡ãœãããšéä¿¡ããŸã
ããç¥ã£ãŠããobjc_msgSendïŒïŒé¢æ°ã¯ãæåã«åŒã³åºãããã¡ãœãããå®è£ ããé¢æ°ãæ¢ããŠããããããã®é¢æ°ãèŠã€ããŠèªåã§åŒã³åºãããšãã§ããŸãã
ã¡ãœããåŒã³åºããããå°ã詳ããç¥ãããšãã§ããå°ããªãã¹ãããã°ã©ã ãæžããŠã¿ãŸãããã
#import <Foundation/Foundation.h> #import <objc/runtime.h> @interface TestClass : NSObject - (void)someMethod; - (void)callSomeMethod; - (void)methodWithParam:(const char *)param; @end @implementation TestClass - (void)someMethod { NSLog(@"Hello from %p.%s!", self, _cmd); } - (void)callSomeMethod { NSLog(@"Hello from %p.%s!", self, _cmd); [self someMethod]; } - (void)methodWithParam:(const char *)param { NSLog(@"Hello from %p.%s! My parameter is: <%s>", self, _cmd, param); } @end int main(int argc, const char * argv[]) { TestClass * myObj = [[TestClass alloc] init]; [myObj someMethod]; [myObj callSomeMethod]; [myObj methodWithParam:"I'm a parameter"]; return 0; }
ããã¥ã¡ã³ããããç®çã®é¢æ°ãåŒã³åºããšãã«ãobjc_msgSendïŒïŒã次ã®é åºã§ãã©ã¡ãŒã¿ãŒãæž¡ãããšãããããŸãã
- ã¡ãœãããåŒã³åºãããªããžã§ã¯ããžã®ãã€ã³ã¿ãŒ
- ã¡ãœãããåŒã³åºããã»ã¬ã¯ã¿ãŒ
- ã¡ãœããã«æž¡ããæ®ãã®åŒæ°
ãããããã¹ãããã°ã©ã ã次ã®ããã«èŠããçç±ã§ããåã¡ãœããã§ããã°selfãš_cmdã«åºåããŸãããããã«ã¯ããããããselfããšã»ã¬ã¯ã¿ãŒãžã®ãã€ã³ã¿ãŒããããŸãã
ãã®ããã°ã©ã ãå®è¡ãããšãåºåã¯ããã次ã®ããã«ãªããŸãã
2015-02-21 12ïŒ43ïŒ18.817 ObjCRuntimeTest [7092ïŒ2454834] 0x1002061f0.someMethodãããââãã«ã¡ã¯ïŒ
2015-02-21 12ïŒ43ïŒ18.818 ObjCRuntimeTest [7092ïŒ2454834] 0x1002061f0.callSomeMethodãããââãã«ã¡ã¯ïŒ
2015-02-21 12ïŒ43ïŒ18.819 ObjCRuntimeTest [7092ïŒ2454834] 0x1002061f0.someMethodãããââãã«ã¡ã¯ïŒ
2015-02-21 12ïŒ43ïŒ18.819 ObjCRuntimeTest [7092ïŒ2454834] 0x1002061f0.methodWithParamããããã«ã¡ã¯ïŒïŒ ç§ã®ãã©ã¡ãŒã¿ãŒã¯ïŒ<ç§ã¯ãã©ã¡ãŒã¿ãŒã§ã>
次ã«ãCèšèªã䜿çšããŠãããã®ã¡ãœãããåŒã³åºããŠã¿ãŸããããè¡ãã«ã¯ãã¯ã©ã¹ã®ã¡ãœãããå®è£ ãããªããžã§ã¯ãããé¢æ°ãžã®ãã€ã³ã¿ãŒãååŸããŸãã Cèšèªã®ã¬ãã«ã§äœæ¥ããŠããããšãèãããšãé¢æ°ãžã®ãã€ã³ã¿ãŒã䜿çšã§ããããã«ããåã決å®ããå¿ èŠããããŸãã ããããã¹ãŠãèæ ®ãããšãmainïŒïŒé¢æ°ã«æ¬¡ã®ã³ãŒãããããŸãã
int main(int argc, const char * argv[]) { typedef void (*MethodWithoutParams)(id, SEL); typedef void (*MethodWithParam)(id, SEL, const char *); TestClass * myObj = [[TestClass alloc] init]; MethodWithoutParams someMethodImplementation = [myObj methodForSelector:@selector(someMethod)]; MethodWithoutParams callSomeMethodImplementation = [myObj methodForSelector:@selector(callSomeMethod)]; MethodWithParam methodWithParamImplementation = [myObj methodForSelector:@selector(methodWithParam:)]; someMethodImplementation(myObj, @selector(someMethod)); callSomeMethodImplementation(myObj, @selector(callSomeMethod)); methodWithParamImplementation(myObj, @selector(methodWithParam:), "I'm a parameter"); return 0; }
ããŠãç§ãã¡ã¯ãã§ã«Cèšèªã®ã¿ã䜿çšããŠã¡ãœãããåŒã³åºããŠããŸããããã®å Žåã®äŸå€ã¯ã»ã¬ã¯ã¿ãŒã®ã¿ã§ãããã¯åã®èšäºã§æ¢ã«ååã«ããã£ãŠããŸãã ç§ãã¡ã«ãšã£ãŠãã©ãã¯ããã¯ã¹ã¯methodForSelectorïŒã¡ãœããã®ã¿ã§ããã
Objective-Cã©ã³ã¿ã€ã ã®ã¡ãã»ãŒãžã³ã°ãšã³ãžã³
Objective-Cã©ã³ã¿ã€ã ã«ã¡ãã»ãŒãžãšã³ãžã³ãå®è£ ããéµã¯ãã³ã³ãã€ã©ãã¯ã©ã¹ãšãªããžã§ã¯ããã©ã®ããã«è¡šçŸãããã§ãã
C ++èšèªã§è¡šçŸããå ŽåãRAMå ã®ãªããžã§ã¯ãã¯ãã¯ã©ã¹ã®åã€ã³ã¹ã¿ã³ã¹ã ãã§ãªããåã¯ã©ã¹ã«å¯ŸããŠãäœæãããŸãã ã€ãŸããåºæ¬ã¯ã©ã¹NSObjectãç¶æ¿ããã¯ã©ã¹ãèšè¿°ãããã®ã¯ã©ã¹ã®2ã€ã®ã€ã³ã¹ã¿ã³ã¹ãäœæããããšã«ãããå®è¡æã«äœæãã2ã€ã®ãªããžã§ã¯ããšã¯ã©ã¹ã® 1ã€ã®ãªããžã§ã¯ããååŸããŸã ã
ãã®ã¯ã©ã¹ã®ãŸãã«ãªããžã§ã¯ãã«ã¯ã芪ã¯ã©ã¹ã®ãªããžã§ã¯ããžã®ãã€ã³ã¿ãŒãšããã£ã¹ãããããŒãã«ãšåŒã°ããã»ã¬ã¯ã¿ãŒãšé¢æ°ã¢ãã¬ã¹ã®å¯Ÿå¿è¡šãå«ãŸããŠããŸãã objc_msgSendïŒïŒé¢æ°ã¯ãæž¡ãããã»ã¬ã¯ã¿ãŒã®ããã«åŒã³åºãå¿ èŠãããç®çã®é¢æ°ãæ€çŽ¢ããã®ã«ããã®ããŒãã«ã䜿çšããŸãã
NSObjectãŸãã¯NSProxyãç¶æ¿ããåã¯ã©ã¹ã«ã¯isaãã£ãŒã«ãããããããã¯ã¯ã©ã¹ãªããžã§ã¯ããžã®ãã€ã³ã¿ãŒãšãŸã£ããåãã§ãã ãªããžã§ã¯ãã®ã¡ãœãããåŒã³åºããšãobjc_msgSendïŒïŒé¢æ°ã¯ã¯ã©ã¹ãªããžã§ã¯ããžã®isaãã€ã³ã¿ãŒã«åŸãããã®ã¡ãœãããå®è£ ããé¢æ°ã®ã¢ãã¬ã¹ãæ¢ããŸãã ãã®ãããªé¢æ°ãèŠã€ãããªãå Žåã¯ã芪ãªããžã§ã¯ãã®ã¯ã©ã¹ã®ãªããžã§ã¯ãã«ç§»åããããã§ãã®é¢æ°ãæ¢ããŸãã ããã¯ãç®çã®æ©èœãèŠã€ãããŸã§çºçããŸãã NSObjectã¯ã©ã¹ã®ãªããžã§ã¯ããå«ãé¢æ°ãã©ãã«ãèŠã€ãããªãã£ãå Žåãæ¢ç¥ã®äŸå€ãã¹ããŒãããŸãã
ã€ã³ã¹ã¿ã³ã¹ã«éä¿¡ãããèªèãããªãã»ã¬ã¯ã¿ãŒ...
ããããå®éã«ã¯...
çŸåšãããªãé
ããã£ãŒãã£ãŒæ€çŽ¢ããã»ã¹ããããã«æ¹åãããŠããŸãã ãªããžã§ã¯ãã®ã¡ãœãããåŒã³åºããšããããèŠã€ãããšãç¹å®ã®ãã£ãã·ã¥ããŒãã«ã«é
眮ãããŸãã ãããã£ãŠããªããžã§ã¯ãã§methodForSelectorïŒã¡ãœãããåŒã³åºããšãç®çã®é¢æ°ãæåã«æ€çŽ¢ãããšãã«NSObjectã¯ã©ã¹ã®ãªããžã§ã¯ãã§é¢æ°ãèŠã€ãã£ããšãã«ãã¯ã©ã¹ã®ããŒãã«ã«ãã£ãã·ã¥ããã次ã«é¢æ°ãæ€çŽ¢ãããŸãããã»ã©æéã¯ããããŸããã
ãŸããã¡ãœããã®å®è£ ãèŠã€ãããªãå Žåãããã«äŸå€ã¯çºçããŸããã Message Forwardingã®ãããªã¡ã«ããºã ããããŸãã
ãŸããã¡ãœããã®å®è£ ãèŠã€ãããªãå Žåãããã«äŸå€ã¯çºçããŸããã Message Forwardingã®ãããªã¡ã«ããºã ããããŸãã
Objective-Cã©ã³ã¿ã€ã ã®ãœãŒã¹ã³ãŒããšNSObjectã¯ã©ã¹ã«åºã¥ããå®éã®èª¿æ»ã§ããã確èªããŸãããã
ãã§ã«ç解ããããã«ãNSObjectã«ã¯methodForForselectorïŒã¡ãœãããããããã®ãœãŒã¹ã³ãŒãã¯æ¬¡ã®ããã«ãªããŸãã
+ (IMP)methodForSelector:(SEL)sel { if (!sel) [self doesNotRecognizeSelector:sel]; return object_getMethodImplementation((id)self, sel); // self - } - (IMP)methodForSelector:(SEL)sel { if (!sel) [self doesNotRecognizeSelector:sel]; return object_getMethodImplementation(self, sel); // self - }
ã芧ã®ãšããããã®ã¡ãœããã¯ã¯ã©ã¹èªäœãšã¯ã©ã¹ãªããžã§ã¯ãã®äž¡æ¹ã«å®è£ ãããŠããŸãã ã©ã¡ãã®å Žåããåãobject_getMethodImplementationïŒïŒé¢æ°ã䜿çšãããŸãã
IMP object_getMethodImplementation(id obj, SEL name) { Class cls = (obj ? obj->getIsa() : nil); return class_getMethodImplementation(cls, name); }
ãããŠïŒ ãïŒobjïŒObj-> getIsaïŒïŒïŒnilïŒãã®æ§æã¯äœã§ããïŒïŒ 確ãã«ããã¹ãŠã®èšäºã§åœŒãã¯ç§ãã¡ã«èšã£ãŠããŸã...
ãããŠãå šäœã¯Objective-C Runtimeãããžã§ã¯ããã¡ã€ã«ã®ãã«ãèšå®ããå§ãŸããŸãã
CLANG_CXX_LANGUAGE_STANDARD = "gnu ++ 0x";
CLANG_CXX_LIBRARY = "libc ++";
ãããŠãããã¯å®å šã«si-plus-plush getIsaïŒïŒã¡ãœããã®å®è£ ã§ã ïŒ
inline Class objc_object::getIsa() { if (isTaggedPointer()) { uintptr_t slot = ((uintptr_t)this >> TAG_SLOT_SHIFT) & TAG_SLOT_MASK; return objc_tag_classes[slot]; } return ISA(); }
äžè¬çã«ãObjective-Cã®ãªããžã§ã¯ãã«ã¯isaãã£ãŒã«ããå«ãŸããŠããå¿ èŠããããŸãã ãŸããã¯ã©ã¹ãªããžã§ã¯ããäŸå€ã§ã¯ãããŸããã
ãã®ãã¹ãŠã®ãã«ãã¯ããªãä¹±éã§ãã method methodForSelectorïŒãªããžã§ã¯ãã¡ãœãããšããŠãã¯ã©ã¹ã¡ãœãããšããŠãããŸã£ããåãå®è£ ãæã£ãŠããŸãã å¯äžã®éãã¯ãæåã®å Žåã¯selfããªããžã§ã¯ããæãã2çªç®ã®å Žåã¯ã¯ã©ã¹ãªããžã§ã¯ããæããŠããããšã§ãã
ãããŒãäžäœäœïŒïŒ ã¯ã©ã¹ãªããžã§ã¯ãã§obj-> getIsaïŒïŒãåŒã³åºãã«ã¯ã©ãããã°ããã§ããïŒ ããã§äœãèµ·ãã£ãŠããŸããïŒ
ããããå®éã«ã¯ãã¯ã©ã¹ãªããžã§ã¯ãã«ã¯ããã®ã¯ã©ã¹ã®ã¯ã©ã¹ãªããžã§ã¯ãããæãåããã£ãŒã«ããå®éã«ãããŸãã æ£ããè¡šçŸãããŠããå Žåã ã¡ã¿ã¯ã©ã¹ãæããŸã ã ãªããžã§ã¯ãã®ã¡ãœããïŒã-ãèšå·ã§å§ãŸãã¡ãœããïŒãåŒã³åºããšããã®å®è£ ããã®ã¯ã©ã¹ã§æ€çŽ¢ãããŸãã ã¯ã©ã¹ã¡ãœããïŒã+ãèšå·ã§å§ãŸãïŒãåŒã³åºããšãã¡ã¿ã¯ã©ã¹ã§ãã®å®è£ ãæ€çŽ¢ãããŸãã
èšäºã®åé ã§å°ãåãã€ããŸãããå®è¡æã«ãã¯ã©ã¹ã®2ã€ã®ãªããžã§ã¯ããäœæãããšãã¯ã©ã¹ã®2ã€ã®ã€ã³ã¹ã¿ã³ã¹ãšã¯ã©ã¹ãªããžã§ã¯ãã®3ã€ã®ãªããžã§ã¯ããåŸããããšèšããŸããã å®éãã¯ã©ã¹ãªããžã§ã¯ãã¯åžžã«ã¡ã¿ã¯ã©ã¹ãªããžã§ã¯ããšäžç·ã«äœæãããŸãã ã€ãŸããæçµçã«4ã€ã®ãªããžã§ã¯ããååŸããŸãã
ãã®ç¡æ³ã®æ¬è³ªå šäœãèŠèŠçã«æ³åããããã«ã ãã®èšäºã®åçãããã«æ¿å ¥ããŸãã
æåŸã«ãé¢æ°class_getMethodImplementationïŒïŒãæçµçã«selfãä»ããŠåŒã³åºãããã±ãŒã¹ã«æ»ããŸãããã
IMP class_getMethodImplementation(Class cls, SEL sel) { IMP imp; if (!cls || !sel) return nil; imp = lookUpImpOrNil(cls, sel, nil, YES/*initialize*/, YES/*cache*/, YES/*resolver*/); // Translate forwarding function to C-callable external version if (!imp) { return _objc_msgForward; } return imp; }
奜å¥å¿itiveçãªäººã¯ãlookUpImpOrNilïŒïŒé¢æ°ãlookUpImpOrForwardïŒïŒé¢æ°ã䜿çšããŠããããšããã¬ãŒã¹ã§ããŸãããã®é¢æ°ã®å®è£ ã¯Appleã®Webãµã€ãã«ãããŸãã ãã®é¢æ°ã¯Cã§èšè¿°ãããŠãããããã¥ã¡ã³ãã«èšè¿°ãããŠãããšããã«ãã¹ãŠãæ©èœããããšã確èªããŸãã
ãŸãšã
æåŸã«ãååãšåæ§ã«ãã¡ãœãããCèšèªã®ã¿ã§åŒã³åºããŸãããã
#import <Foundation/Foundation.h> #import <objc/runtime.h> @interface TestClass : NSObject @end @implementation TestClass + (void)someClassMethod { NSLog(@"Hello from some class method!"); } - (void)someInstanceMethod { NSLog(@"Hello from some instance method!"); } @end int main(int argc, const char * argv[]) { typedef void (*MyMethodType)(id, SEL); TestClass * myObj = [[TestClass alloc] init]; Class myObjClassObject = object_getClass(myObj); Class myObjMetaclassObject = object_getClass(myObjClassObject); MyMethodType instanceMethod = class_getMethodImplementation(myObjClassObject, @selector(someInstanceMethod)); MyMethodType classMethod = class_getMethodImplementation(myObjMetaclassObject, @selector(someClassMethod)); instanceMethod(myObj, @selector(someInstanceMethod)); classMethod(myObjClassObject, @selector(someClassMethod)); return 0; }
å®éãObjective Cã®ã¡ãã»ãŒãžã¡ã«ããºã ãç解ããã«ã¯ãŸã ã»ã©é ãã§ããããšãã°ãåŒã³åºãããã¡ãœããããçµæãè¿ãæ¹æ³ãããããŸããã ãããã次ã®éšåã§ããã«ã€ããŠèªãã§ãã ãã:)ã