那在什么场景中会出现这种情况呢?
如果一个包含文字的输入元素有焦点,然后按钮的点击会导致输入失去焦点,然后接下来在输入时双按会重新得到焦点并从弹出bar中选择剪切复制粘贴,就会导致此error。
也就是说当WebView页面中的HTML中有如下代码的时候
<input type="text"> <input type="button" >
即有输入框和按钮的时候,会出现 [UIWebView cut:]: unrecognized selector sent to instance 的错误风险
简单的说就是若有一个WebView中有输入框,又有按钮的话,执行下面的操作就会出现这样的错误:
1.在输入框中输入内容。
2.点击Button让键盘消失。
3。双击输入框中的内容出现选择的bar后点击剪贴。就会出现闪退的现象。
的具体错误如下:
2015-11-20 11:20:59.495 WebViewCutErrorDemo[3381:595295] -[UIWebView cut:]: unrecognized selector sent to instance 0x7f9612f19f40 2015-11-20 11:20:59.497 WebViewCutErrorDemo[3381:595295] *** Terminating app due to uncaught exception ‘NSInvalidArgumentException‘, reason: ‘-[UIWebView cut:]: unrecognized selector sent to instance 0x7f9612f19f40‘ *** First throw call stack: ( 0 CoreFoundation 0x000000010ddb6f45 __exceptionPreprocess + 165 1 libobjc.A.dylib 0x000000010d82edeb objc_exception_throw + 48 2 CoreFoundation 0x000000010ddbf56d -[NSObject(NSObject) doesNotRecognizeSelector:] + 205 3 CoreFoundation 0x000000010dd0ceea ___forwarding___ + 970 4 CoreFoundation 0x000000010dd0ca98 _CF_forwarding_prep_0 + 120 5 UIKit 0x000000010e6a3923 -[UICalloutBar buttonPressed:] + 414 6 UIKit 0x000000010e6a1e47 -[UICalloutBarButton fadeAndSendAction] + 81 7 Foundation 0x000000010d416c39 __NSFireDelayedPerform + 402 8 CoreFoundation 0x000000010dd17264 __CFRUNLOOP_IS_CALLING_OUT_TO_A_TIMER_CALLBACK_FUNCTION__ + 20 9 CoreFoundation 0x000000010dd16e11 __CFRunLoopDoTimer + 1089 10 CoreFoundation 0x000000010dcd8821 __CFRunLoopRun + 1937 11 CoreFoundation 0x000000010dcd7e08 CFRunLoopRunSpecific + 488 12 GraphicsServices 0x000000011158fad2 GSEventRunModal + 161 13 UIKit 0x000000010e16430d UIApplicationMain + 171 14 WebViewCutErrorDemo 0x000000010d32c86f main + 111 15 libdyld.dylib 0x00000001104f292d start + 1 ) libc++abi.dylib: terminating with uncaught exception of type NSException
仔细想想第三方登录的页面有出现这种问题的风险。
有人说这里面说是苹果系统的bug,原因是这种操作在响应链不能正确的发送,并最终发送到UIWebView的实例,而不是内部的UIWebDocumentView。
下面提供一下这种问题的解决方案,思想就是动态的为UIWebView添加响应的方法。
新建一个类 CutCopyPasteFixedWebView 继承 UIWebView
CutCopyPasteFixedWebView.h代码如下
// // CutCopyPasteFixedWebView.h // WebViewCutErrorDemo // // Created by lidaojian on 15/11/20. // Copyright © 2015年 lidaojian. All rights reserved. // #import <UIKit/UIKit.h> @interface CutCopyPasteFixedWebView : UIWebView @end
CutCopyPasteFixedWebView.m代码如下
// // CutCopyPasteFixedWebView.m // WebViewCutErrorDemo // // Created by lidaojian on 15/11/20. // Copyright © 2015年 lidaojian. All rights reserved. // #import "CutCopyPasteFixedWebView.h" #import <objc/runtime.h> @implementation CutCopyPasteFixedWebView - (instancetype)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { /// 适配防止崩溃 [self prepareForNoCrashes]; } return self; } - (UIView *)internalView { static const char internalViewKey = ‘\0‘; /// 动态关联 UIView *internalView = objc_getAssociatedObject(self, &internalViewKey); if (internalView == nil && self.subviews.count > 0) { for (UIView *view in self.scrollView.subviews) { if ([[view.class description] hasPrefix:@"UIWeb"]) { internalView = view; objc_setAssociatedObject(self, &internalView, view, OBJC_ASSOCIATION_ASSIGN); break; } } } return internalView; } void webViewImplementUIResponderStandardEditActions(id self, SEL selector, id param) { /// IMP本质就是函数指针 methodForSelector 获得一个指向方法实现的指针,并可以使用该指针直接调用方法实现 IMP imp = [[self internalView] methodForSelector:selector]; /// 函数指针 void (*method)(id, SEL, id) = (void (*) (id, SEL, id))imp; /// 直接用函数指针调用方法 method([self internalView], selector, param); } - (void)prepareForNoCrashes { NSArray *selectors = @[@"cut:", @"copy:", @"paste:", @"select:", @"selectAll:", @"delete:", @"makeTextWritingDirectionLeftToRight:", @"makeTextWritingDirectionRightToLeft:", @"toggleBoldface:", @"toggleItalics:", @"toggleUnderline:", @"increaseSize:", @"decreaseSize:"]; for (NSString *selName in selectors) { /// 动态的根据方法名来获取方法 SEL selector = NSSelectorFromString(selName); /// 若父类没有实现则给父类添加selector方法,若父类实现了,并不修改父类的selector方法 class_addMethod(self.class, selector, (IMP)webViewImplementUIResponderStandardEditActions, ""); } } @end
另外附上测试的HTML文件
<html> <head> </head> <body> <br><br> <input type="text"> <input type="button" > </body </html>
若有疑问请加本人QQ:610774281。一起探讨一起进步。。。。
参考连接:
http://stackoverflow.com/questions/21316784/uiwebview-bug-uiwebview-cut-unrecognized-selector-sent-to-instance#
时间: 2024-11-15 22:45:42