UIWebView: отключить параметры копирования / вырезания для редактора форматированного текста.

У меня есть UIWebView с div contentEditable, чтобы реализовать какой-то редактор форматированного текста. Мне нужно обрезать параметры копирования и вырезания в UIMenuController, которые появляются в веб-представлении, когда пользователь выбирает любой фрагмент текста.

Кажется, в Интернете есть много решений, но по какой-то причине ни одно из них не подходит для моего сценария.

Я создал подкласс UIWebView и реализовал canPerformAction:(SEL)action withSender:, чтобы удалить копию и вырезать, но как только пользователь выбирает «Выбрать» или «Выбрать все», появляется новое меню, и, очевидно, веб-представление не перехватывает это действие и canPerform метод не вызывается.

введите описание изображения здесь

Есть ли способ урезать действия для этих случаев?


person Omer    schedule 15.08.2013    source источник


Ответы (1)


Я адаптирую другой свой ответ для вашего случая.

canPerformAction: фактически вызывается во внутреннем UIWebDocumentView вместо UIWebView, который вы обычно не можете создать подкласс. С некоторой магией времени выполнения это возможно.

Мы создаем класс, у которого есть один метод:

@interface _SwizzleHelper : UIView @end

@implementation _SwizzleHelper

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

@end

Когда у вас есть веб-представление, действиями которого вы хотите управлять, вы перебираете его подвиды прокрутки и берете класс UIWebDocumentView. Затем мы динамически делаем суперкласс класса, который мы создали выше, как класс подпредставления (UIWebDocumentView - но мы не можем сказать это заранее, потому что это частный API), и заменяем класс подпредставления на наш класс.

#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);
}
person Leo Natan    schedule 16.01.2015
comment
Интересный подход. Мне интересно, почему вы динамически создаете новый подкласс UIWebDocumentView. Разве не было бы проще просто сдвинуть -canPerformAction: из UIWebDocumentView напрямую? - person Ortwin Gentz; 17.01.2015
comment
Это возможно, но это проще реализовать. Легче вызвать суперреализацию, проще переопределить метод независимо от того, какой класс реализует его в цепочке суперклассов. Если бы вы использовали метод напрямую, вам нужно было бы выяснить, какой суперкласс реализует его первым, и это может быть проблематично, если класс используется в другом месте. - person Leo Natan; 17.01.2015
comment
Вы можете поделиться демо для этого. В моем коде он все еще не работает. - person Sonu; 17.01.2015