UIWebView: Деактивирайте опциите за копиране/изрязване за редактор с форматиран текст

Имам UIWebView с contentEditable div, за да внедря някакъв вид редактор на богат текст. Трябва да отрежа опциите за копиране и изрязване в 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