OC Rumtime—IMP的函數調用

        最近在學習OC 運行時(runtime),測試了一個函數class_replaceMethod,具體如下:

IMP originalMethod;
NSString *CustomUppercaseString(id SELF,SEL _CMD){
    NSLog(@"BeginConverting。。。");
    NSString *result=originalMethod(SELF,_CMD);
    NSLog(@"EndConverting。。。");
    return result;
}

Implementation中:

- (void)runtimeTest{
    originalMethod=[NSString instanceMethodForSelector:@selector(uppercaseString)];
    class_replaceMethod([NSString class], @selector(uppercaseString), (IMP)MyUppercaseString,NULL);
    NSString *s=@"zhang lei";
    NSLog(@"uppercase:%@",[s uppercaseString]);
}

運行過程中在下面這行報錯:

NSString *result=originalMethod(SELF,_CMD);

①先是提示參數太多,問百度說是IMP本身包含了self和_cmd倆參數,不用再顯示傳參。去掉參數後繼續報錯。

②提示在ARC下無法將void *轉換爲id。關閉ARC後依舊出錯,還是無法轉換。

        當我查看IMP的定義時發現了這個:

/// A pointer to the function of a method implementation. 
#if !OBJC_OLD_DISPATCH_PROTOTYPES
typedef void (*IMP)(void /* id, SEL, ... */ ); 
#else
typedef id (*IMP)(id, SEL, ...); 
#endif

報錯的主要原因是因爲IMP取的是if中的定義,返回void *,於是懷疑項目編譯設置上設置的不對。繼續搜百度找到如下內容:

“使用XCode6.X的小夥伴們要特別注意了,需要先到項目的構建設置裏面把Apple LLVM 6.0 - Preprocessing 的Enable Strict Checking of objc_msgSend Calls 選項設置爲NO,否則result = imp(clazz, sel);會報錯的!!”

http://www.ithao123.cn/content-450798.html

於是按照上面說的進行了設置,運行成功。並且經過調試,發現確實是Enable Strict Checking of objc_msgSend Calls控制着OBJC_OLD_DISPATCH_PROTOTYPES的取值。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章