intercept copy, paste, define popover in UIWebView

后端 未结 1 2033
臣服心动
臣服心动 2021-02-03 15:17

When we highlight a text in UIWebView usually the copy, paste, define.. etc appears. How can I intercept this so that when I choose copy I call some other method/do something el

相关标签:
1条回答
  • 2021-02-03 15:55

    You can simply override -copy:

    - (void)copy:(id)sender
    {
        // Do something else here
        return [super copy:sender];
    }
    

    Edit to answer your comment.

    Define is a bit trickier, since it's private. However, you could implement your own method. Set up the UIMenuController with your desired items.

    UIMenuItem *copyItem = [[UIMenuItem alloc] initWithTitle:@"Copy" 
                                                      action:@selector(myCopy:)];
    
    UIMenuItem *defineItem = [[UIMenuItem alloc] initWithTitle:@"Define"
                                                        action:@selector(myDefine:)];
    
    [[UIMenuController sharedMenuController] setMenuItems:[NSArray arrayWithObjects:defineItem, copyItem, nil]];
    [defineItem release];
    [copyItem release];
    

    Then you implement those methods.

    As for define, it's way more complicated.. First, you need to check if the UIReferenceLibraryController has a definition, by overriding -canPerformAction:withSender:

    - (BOOL)canPerformAction:(SEL)action withSender:(id)sender 
    {
        if (action == @selector(myDefine:)) {
            // Make sure we are on iOS5.x
            if (NSClassFromString(@"UIReferenceLibraryViewController")) {
                return [UIReferenceLibraryViewController dictionaryHasDefinitionForTerm:[webView selectedText]];
            }
        }
        // Implement other custom actions here
        return NO;
    }
    

    -selectedText is here a category on UIWebView:

    - (NSString *)selectedText {
        return [self stringByEvaluatingJavaScriptFromString:@"window.getSelection().toString()"];
    }
    

    Then you need to implement myDefine:

    - (void)myDefine:(UIMenuController *)menuController 
    {    
        CGRect selectedWordFrame = [webView rectForSelectedText];
    
        UIReferenceLibraryViewController *dict = [[UIReferenceLibraryViewController alloc] initWithTerm:[webView selectedText]];
        UIPopoverController *popover = [[UIPopoverController alloc] initWithContentViewController:dict];
        [popover presentPopoverFromRect:selectedWordFrame
                                 inView:webView
               permittedArrowDirections:UIPopoverArrowDirectionAny
                               animated:YES];
        [popover setDelegate:self];
        [dict release];
    }
    - (void)popoverControllerDidDismissPopover:(UIPopoverController *)popoverController 
    {
        [popoverController release];
    }
    

    Edit to answer you comment again

    -rectForSelectedText is another custom category on UIWebView.

    - (CGRect)rectForSelectedText {
        return CGRectFromString([self stringByEvaluatingJavaScriptFromString:@"getRectForSelectedWord()"]);
    }
    

    What it does is calling a javascript that returns a string that you can convert using CGRectFromString(), it looks something like this:

    function getRectForSelectedWord() {
        var selection = window.getSelection();
        var range = selection.getRangeAt(0);
        var rect = range.getBoundingClientRect();
        return "{{" + rect.left + "," + rect.top + "}, {" + rect.width + "," + rect.height + "}}";
    }
    

    Check this page to learn how to inject javascript into UIWebView.

    0 讨论(0)
提交回复
热议问题