代碼如下:
+ (void)load{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
Class class = [NSURLConnection class];
SEL selector = @selector(initWithRequest:delegate:);
SEL swizzledSelector = @selector(test_initWithRequest:delegate:);
Method originalinitWithRequest = class_getInstanceMethod(class, selector);
NSURLConnection* (^swizzleBlock)(NSURLConnection *,SEL,NSURLRequest*,id )= ^(NSURLConnection *slf,SEL swizzledSelector,NSURLRequest *request,id delegate) {
return ((NSURLConnection*(*)(NSURLConnection*,SEL,NSURLRequest*,id))objc_msgSend)(slf,swizzledSelector,request,delegate);
};
IMP implementation = imp_implementationWithBlock(swizzleBlock);
class_addMethod(class, swizzledSelector, implementation, method_getTypeEncoding(originalinitWithRequest));
Method newConnectionWithRequestClassMethod = class_getInstanceMethod(class, swizzledSelector);
method_exchangeImplementations(originalinitWithRequest, newConnectionWithRequestClassMethod);
});
}
我看了半天沒發(fā)現(xiàn)什么問題,為什么這樣一交換之后運行就會崩潰。
在return 時候打斷點,信息如下:
(lldb) po slf
<NSURLConnection: 0x60000000dea0> { request: (null) }
(lldb) po swizzledSelector
<NSURLRequest: 0x60000000e020> { URL: http://httpstat.us/200 }
(lldb) po request
<ViewController: 0x7fdd4bf03fe0>
(lldb) po delegate
nil
崩潰信息如下:
2017-12-19 15:09:25.923 HookNetwork2[4030:501650] *** NSForwarding: warning: selector (0x60000000e020) for message 'X?ü' does not match selector known to Objective C runtime (0x608000004340)-- abort
2017-12-19 15:09:25.924 HookNetwork2[4030:501650] (null): unrecognized selector sent to instance 0x60000000dea0
2017-12-19 15:09:25.928 HookNetwork2[4030:501650] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '(null): unrecognized selector sent to instance 0x60000000dea0'
*** First throw call stack:
(
0 CoreFoundation 0x000000010926fb0b __exceptionPreprocess + 171
1 libobjc.A.dylib 0x0000000108cd4141 objc_exception_throw + 48
2 CoreFoundation 0x00000001092df134 -[NSObject(NSObject) doesNotRecognizeSelector:] + 132
3 CoreFoundation 0x00000001091f6840 ___forwarding___ + 1024
4 CoreFoundation 0x00000001091f63b8 _CF_forwarding_prep_0 + 120
5 HookNetwork2 0x00000001086fc379 __20+[RAObserverer load]_block_invoke_2 + 153
6 HookNetwork2 0x00000001086fd6a3 -[ViewController connectTest:] + 1731
7 UIKit 0x0000000109694d82 -[UIApplication sendAction:to:from:forEvent:] + 83
8 UIKit 0x00000001098195ac -[UIControl sendAction:to:forEvent:] + 67
9 UIKit 0x00000001098198c7 -[UIControl _sendActionsForEvents:withEvent:] + 450
10 UIKit 0x0000000109818802 -[UIControl touchesEnded:withEvent:] + 618
11 UIKit 0x00000001097027ea -[UIWindow _sendTouchesForEvent:] + 2707
12 UIKit 0x0000000109703f00 -[UIWindow sendEvent:] + 4114
13 UIKit 0x00000001096b0a84 -[UIApplication sendEvent:] + 352
14 UIKit 0x0000000109e945d4 __dispatchPreprocessedEventFromEventQueue + 2926
15 UIKit 0x0000000109e8c532 __handleEventQueue + 1122
16 CoreFoundation 0x0000000109215c01 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 17
17 CoreFoundation 0x00000001091fb0cf __CFRunLoopDoSources0 + 527
18 CoreFoundation 0x00000001091fa5ff __CFRunLoopRun + 911
19 CoreFoundation 0x00000001091fa016 CFRunLoopRunSpecific + 406
20 GraphicsServices 0x000000010d044a24 GSEventRunModal + 62
21 UIKit 0x0000000109693134 UIApplicationMain + 159
22 HookNetwork2 0x00000001086ff2bf main + 111
23 libdyld.dylib 0x000000010c0d965d start + 1
24 ??? 0x0000000000000001 0x0 + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException
前面的代碼哪里有問題,為什么斷點信息是這樣的?
這里有一個crash demo,可以下載下來看一看。
建議閱讀一下imp_implementationWithBlock的文檔。
Parameters
block
The block that implements this method. The signature of block should be method_return_type ^(id self, self, method_args …). The selector of the method is not available to block. block is copied with Block_copy().
你的代碼里面的block的類型里面是需要了一個seletor, 打斷點的得知,此時swizzle selector的值是一個NSURLRequest,明顯不是我們想要的selector,所以objc_msgSend就失敗了。
查閱文檔可知,block的簽名應該是method_return_type ^(id self, self, method_args …).是不需要SEL的,所以將上述的代碼改為:
id swizzleBlock = ^(NSURLConnection *slf, NSURLRequest *request,id delegate) {
return ((NSURLConnection*(*)(NSURLConnection*,SEL,NSURLRequest*,id))objc_msgSend)(slf,swizzledSelector,request,delegate);
};
運行可以成功,點擊按鈕也OK了。
那個RAObserverer是什么東西?代碼里沒有,奔潰調(diào)用棧里看起來跟上面代碼沒關系。
需要知道這兩句是干了什么,從調(diào)用??词?code>RAObserverer沒有load
方法的實現(xiàn)
5 HookNetwork2 0x00000001086fc379 __20+[RAObserverer load]_block_invoke_2 + 153
6 HookNetwork2 0x00000001086fd6a3 -[ViewController connectTest:] + 1731
關鍵:imp_implementationWithBlock這個block的參數(shù)里是沒有SEL的
北大青鳥APTECH成立于1999年。依托北京大學優(yōu)質(zhì)雄厚的教育資源和背景,秉承“教育改變生活”的發(fā)展理念,致力于培養(yǎng)中國IT技能型緊缺人才,是大數(shù)據(jù)專業(yè)的國家
北大青鳥中博軟件學院創(chuàng)立于2003年,作為華東區(qū)著名互聯(lián)網(wǎng)學院和江蘇省首批服務外包人才培訓基地,中博成功培育了近30000名軟件工程師走向高薪崗位,合作企業(yè)超4
中公教育集團創(chuàng)建于1999年,經(jīng)過二十年潛心發(fā)展,已由一家北大畢業(yè)生自主創(chuàng)業(yè)的信息技術與教育服務機構(gòu),發(fā)展為教育服務業(yè)的綜合性企業(yè)集團,成為集合面授教學培訓、網(wǎng)
達內(nèi)教育集團成立于2002年,是一家由留學海歸創(chuàng)辦的高端職業(yè)教育培訓機構(gòu),是中國一站式人才培養(yǎng)平臺、一站式人才輸送平臺。2014年4月3日在美國成功上市,融資1
曾工作于聯(lián)想擔任系統(tǒng)開發(fā)工程師,曾在博彥科技股份有限公司擔任項目經(jīng)理從事移動互聯(lián)網(wǎng)管理及研發(fā)工作,曾創(chuàng)辦藍懿科技有限責任公司從事總經(jīng)理職務負責iOS教學及管理工作。
浪潮集團項目經(jīng)理。精通Java與.NET 技術, 熟練的跨平臺面向?qū)ο箝_發(fā)經(jīng)驗,技術功底深厚。 授課風格 授課風格清新自然、條理清晰、主次分明、重點難點突出、引人入勝。
精通HTML5和CSS3;Javascript及主流js庫,具有快速界面開發(fā)的能力,對瀏覽器兼容性、前端性能優(yōu)化等有深入理解。精通網(wǎng)頁制作和網(wǎng)頁游戲開發(fā)。
具有10 年的Java 企業(yè)應用開發(fā)經(jīng)驗。曾經(jīng)歷任德國Software AG 技術顧問,美國Dachieve 系統(tǒng)架構(gòu)師,美國AngelEngineers Inc. 系統(tǒng)架構(gòu)師。