为什么会崩溃?

代码如下:
+(void)load{
staticdispatch_once_tonceToken;
dispatch_once(&onceToken,^{
Classclass=[NSURLConnectionclass];
SELselector=@selector(initWithRequest:delegate:);
SELswizzledSelector=@selector(test_initWithRequest:delegate:);
MethodoriginalinitWithRequest=class_getInstanceMethod(class,selector);
NSURLConnection*(^swizzleBlock)(NSURLConnection*,SEL,NSURLRequest*,id)=^(NSURLConnection*slf,SELswizzledSelector,NSURLRequest*request,iddelegate){
return((NSURLConnection*(*)(NSURLConnection*,SEL,NSURLRequest*,id))objc_msgSend)(slf,swizzledSelector,request,delegate);
};
IMPimplementation=imp_implementationWithBlock(swizzleBlock);
class_addMethod(class,swizzledSelector,implementation,method_getTypeEncoding(originalinitWithRequest));
MethodnewConnectionWithRequestClassMethod=class_getInstanceMethod(class,swizzledSelector);
method_exchangeImplementations(originalinitWithRequest,newConnectionWithRequestClassMethod);
});
}
我看了半天没发现什么问题,为什么这样一交换之后运行就会崩溃。在return时候打断点,信息如下:
(lldb)poslf
{request:(null)}
(lldb)poswizzledSelector
{URL:http://httpstat.us/200}
(lldb)porequest
(lldb)podelegate
nil
崩溃信息如下:
2017-12-1915:09:25.923HookNetwork2[4030:501650]***NSForwarding:warning:selector(0x60000000e020)formessage'Xˆü'doesnotmatchselectorknowntoObjectiveCruntime(0x608000004340)--abort
2017-12-1915:09:25.924HookNetwork2[4030:501650](null):unrecognizedselectorsenttoinstance0x60000000dea0
2017-12-1915:09:25.928HookNetwork2[4030:501650]***Terminatingappduetouncaughtexception'NSInvalidArgumentException',reason:'(null):unrecognizedselectorsenttoinstance0x60000000dea0'
***Firstthrowcallstack:
(
0CoreFoundation0x000000010926fb0b__exceptionPreprocess+171
1libobjc.A.dylib0x0000000108cd4141objc_exception_throw+48
2CoreFoundation0x00000001092df134-[NSObject(NSObject)doesNotRecognizeSelector:]+132
3CoreFoundation0x00000001091f6840___forwarding___+1024
4CoreFoundation0x00000001091f63b8_CF_forwarding_prep_0+120
5HookNetwork20x00000001086fc379__20+[RAObservererload]_block_invoke_2+153
6HookNetwork20x00000001086fd6a3-[ViewControllerconnectTest:]+1731
7UIKit0x0000000109694d82-[UIApplicationsendAction:to:from:forEvent:]+83
8UIKit0x00000001098195ac-[UIControlsendAction:to:forEvent:]+67
9UIKit0x00000001098198c7-[UIControl_sendActionsForEvents:withEvent:]+450
10UIKit0x0000000109818802-[UIControltouchesEnded:withEvent:]+618
11UIKit0x00000001097027ea-[UIWindow_sendTouchesForEvent:]+2707
12UIKit0x0000000109703f00-[UIWindowsendEvent:]+4114
13UIKit0x00000001096b0a84-[UIApplicationsendEvent:]+352
14UIKit0x0000000109e945d4__dispatchPreprocessedEventFromEventQueue+2926
15UIKit0x0000000109e8c532__handleEventQueue+1122
16CoreFoundation0x0000000109215c01__CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__+17
17CoreFoundation0x00000001091fb0cf__CFRunLoopDoSources0+527
18CoreFoundation0x00000001091fa5ff__CFRunLoopRun+911
19CoreFoundation0x00000001091fa016CFRunLoopRunSpecific+406
20GraphicsServices0x000000010d044a24GSEventRunModal+62
21UIKit0x0000000109693134UIApplicationMain+159
22HookNetwork20x00000001086ff2bfmain+111
23libdyld.dylib0x000000010c0d965dstart+1
24???0x00000000000000010x0+1
)
libc++abi.dylib:terminatingwithuncaughtexceptionoftypeNSException
前面的代码哪里有问题,为什么断点信息是这样的?这里有一个crashdemo,可以下载下来看一看。
MYYA
浏览 585回答 2
2回答

慕容森

建议阅读一下imp_implementationWithBlock的文档。ParametersblockTheblockthatimplementsthismethod.Thesignatureofblockshouldbemethod_return_type^(idself,self,method_args…).Theselectorofthemethodisnotavailabletoblock.blockiscopiedwithBlock_copy().你的代码里面的block的类型里面是需要了一个seletor,打断点的得知,此时swizzleselector的值是一个NSURLRequest,明显不是我们想要的selector,所以objc_msgSend就失败了。查阅文档可知,block的签名应该是method_return_type^(idself,self,method_args…).是不需要SEL的,所以将上述的代码改为:idswizzleBlock=^(NSURLConnection*slf,NSURLRequest*request,iddelegate){return((NSURLConnection*(*)(NSURLConnection*,SEL,NSURLRequest*,id))objc_msgSend)(slf,swizzledSelector,request,delegate);};运行可以成功,点击按钮也OK了。

慕妹3242003

那个RAObserverer是什么东西?代码里没有,奔溃调用栈里看起来跟上面代码没关系。需要知道这两句是干了什么,从调用栈看是RAObserverer没有load方法的实现5HookNetwork20x00000001086fc379__20+[RAObservererload]_block_invoke_2+1536HookNetwork20x00000001086fd6a3-[ViewControllerconnectTest:]+1731关键:imp_implementationWithBlock这个block的参数里是没有SEL的
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

JavaScript