美文网首页专注iOS开发(OC/Swift)
iOS 错误 [UIWebView paste:]: unrec

iOS 错误 [UIWebView paste:]: unrec

作者: 洲洲哥 | 来源:发表于2018-12-20 19:30 被阅读33次

    出现控件:目前只在UIWebView中出现 切记!!!

    那在什么场景中会出现这种情况呢?

    如果一个包含文字的输入元素有焦点,然后按钮的点击会导致输入失去焦点,然后接下来在输入时双按会重新得到焦点并从弹出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添加响应的方法。

    新建一个类 FixedWebView 继承 UIWebView

    FixedWebView.h代码如下

    //
    //  FixedWebView.h
    //  webView
    //
    //  Created by zzg on 2018/12/20.
    //  Copyright © 2018年 zzg. All rights reserved.
    //
    
    #import <UIKit/UIKit.h>
    
    @interface FixedWebView : UIWebView
    
    @end
    

    FixedWebView.m代码如下

    //
    //  FixedWebView.m
    //  webView
    //
    //  Created by zzg on 2018/12/20.
    //  Copyright © 2018年 zzg. All rights reserved.
    //
    
    #import "FixedWebView.h"
    #import <objc/runtime.h>
    
    @implementation FixedWebView
    - (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
    
    

    有些地方说的不到位,还请各位看官指正。。。

    • 如有问题可添加QQ群:234812704
    • 欢迎各位一块学习,提高逼格!
    • 也可以添加洲洲哥的微信公众号

    可以来微信公众号(洲洲哥)后台给我们留言。 快来扫码关注我们吧!

    公众号二维码

    相关文章

      网友评论

        本文标题:iOS 错误 [UIWebView paste:]: unrec

        本文链接:https://www.haomeiwen.com/subject/unsukqtx.html