UIWebView: Disable copy/cut options for a rich tex

2019-07-20 20:59发布

I have a UIWebView with a contentEditable div in order to implement some kind of rich text editor. I need to trimm the copy & cut options in the UIMenuController that appears in the web view once the user selects any piece of text.

There seems to be a lot of solutions around the web, but for some reason, non of them applies for my scenario.

I've subclassed the UIWebView and implemented the canPerformAction:(SEL)action withSender: to remove the copy and cut, but once the user chooses "Select" or "Select All", a new menu appears, and apparently, the web view does not intercept this action and the canPerform method is not being called.

enter image description here

Is there a way to trimm actions for this cases?

1条回答
一纸荒年 Trace。
2楼-- · 2019-07-20 21:19

I will adapt another answer of mine for your case.

The canPerformAction: is actually called on the internal UIWebDocumentView instead of the UIWebView, which you cannot normally subclass. With some runtime magic, it's possible.

We create a class which has one method:

@interface _SwizzleHelper : UIView @end

@implementation _SwizzleHelper

-(BOOL)canPerformAction:(SEL)action
{
    //Your logic here
    return NO;
}

@end

Once you have a web view which you want to control the actions of, you iterate its scroll view's subviews and take the UIWebDocumentView class. We then dynamically make the superclass of the class we created above to be the subview's class (UIWebDocumentView - but we cannot say that upfront because this is private API), and replace the subview's class to our class.

#import "objc/runtime.h"    

-(void)__subclassDocumentView
{
    UIView* subview;

    for (UIView* view in self.scrollView.subviews) {
        if([[view.class description] hasPrefix:@"UIWeb"])
            subview = view;
    }

    if(subview == nil) return; //Should not stop here

    NSString* name = [NSString stringWithFormat:@"%@_SwizzleHelper", subview.class.superclass];
    Class newClass = NSClassFromString(name);

    if(newClass == nil)
    {
        newClass = objc_allocateClassPair(subview.class, [name cStringUsingEncoding:NSASCIIStringEncoding], 0);
        if(!newClass) return;

        Method method = class_getInstanceMethod([_SwizzleHelper class], @selector(canPerformAction:));
        class_addMethod(newClass, @selector(canPerformAction:), method_getImplementation(method), method_getTypeEncoding(method));

        objc_registerClassPair(newClass);
    }

    object_setClass(subview, newClass);
}
查看更多
登录 后发表回答