UIWebView Bug: -[UIWebView cut:]: unrecognized selector sent to instance

后端 未结 4 1745
时光取名叫无心
时光取名叫无心 2021-02-04 03:43

In the UIWebView, if an input element containing text has focus, and a button is pressed that causes the input to lose focus, then subsequently double-tapping on th

4条回答
  •  不思量自难忘°
    2021-02-04 04:13

    This is an Apple bug. The problem is the cut: action is sent incorrectly in the responder chain, and ends up being sent to the UIWebView instance instead of the internal UIWebDocumentView, which implements the method.

    Until Apple fixes the bug, let's have some fun with the Objective C runtime.

    Here, I subclass UIWebView with the purpose of supporting all UIResponderStandardEditActions methods, by forwarding them to the correct internal instance.

    @import ObjectiveC;    
    
    @interface CutCopyPasteFixedWebView : UIWebView @end
    
    @implementation CutCopyPasteFixedWebView
    
    - (UIView*)_internalView
    {
        UIView* internalView = objc_getAssociatedObject(self, "__internal_view_key");
    
        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, "__internal_view_key", view, OBJC_ASSOCIATION_ASSIGN);
    
                    break;
                }
            }
        }
    
        return internalView;
    }
    
    void webView_implement_UIResponderStandardEditActions(id self, SEL selector, id param)
    {
        void (*method)(id, SEL, id) = (void(*)(id, SEL, id))[[self _internalView] methodForSelector:selector];
    
        //Call internal implementation.
        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);
    
            //This is safe, the method will fail if there is already an implementation.
            class_addMethod(self.class, selector, (IMP)webView_implement_UIResponderStandardEditActions, "");
        }
    }
    
    - (void)awakeFromNib
    {
        [self _prepareForNoCrashes];
    
        [super awakeFromNib];
    }
    
    @end
    

    Use this subclass in your storyboard.

    Have fun.

提交回复
热议问题