2

I have a UIWebView which loads a HTML string and content can be added to doing using Javascript.

Is there any way to know when something (text or an image) has been pasted in the web view.

NSString *path = [[NSBundle mainBundle] pathForResource:@"htmlString" ofType:@"txt"];
NSString *htmlString = [[NSString alloc] initWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil];
[self.ibWebView loadHTMLString:htmlString baseURL:nil];


- (void)webViewDidFinishLoad:(UIWebView *)webView
{
    NSString *jsToEncloseInEditableContainer = [NSString stringWithFormat:@"function contentedited(e){window.location='mpscontentedited://' + e.keyCode;};(function() {var body = document.body;var contentContainer =  document.createElement('div');contentContainer.id = 'content';contentContainer.setAttribute('contenteditable','true');contentContainer.style.fontFamily=' Helvetica';contentContainer.style.marginTop=\"15px\";contentContainer.onkeydown = contentedited;contentContainer.onpaste=contentedited;var node;while(node=body.firstChild) {contentContainer.appendChild(node);}body.appendChild(contentContainer);%@body=undefined;delete body;contentContainer=undefined;delete contentContainer;node=undefined;delete node;})();", @"contentContainer.focus();"];
    [self.ibWebView stringByEvaluatingJavaScriptFromString:jsToEncloseInEditableContainer];
}

I have tried overriding UIResponder's paste: method, but it never gets called.

- (void)paste:(id)sender
{
    NSLog(@"paste not called");
}

I have also tried to creating a custom menu button

UIMenuController *menu = [UIMenuController sharedMenuController];
UIMenuItem *item = [[UIMenuItem alloc] initWithTitle:@"Paste Custom" action:@selector(pasteCustom:)];
[menu setMenuItems:@[item]];
[menu setMenuVisible:YES];

- (BOOL)canPerformAction:(SEL)action withSender:(id)sender
{
    if (action == @selector(pasteCustom:))
    {
        return YES;
    }
    return [super canPerformAction:action withSender:sender];
}

- (void)pasteCustom:(id)sender
{
    NSLog(@"paste custom");
    [super paste:sender]; // --> calling this causes a crash (unrecognized selector sent to instance)
}

What am I doing wrong?

I either want to know when something is pasted or I want to have a custom menu button that behaves similar to default paste button.

Thanks in advance.

vivek241
  • 666
  • 1
  • 7
  • 18

2 Answers2

3

Casting is not magic.

I repeat: Casting is not magic!

It does't change the run-time type of an object. If it didn't respond to a selector as a UIWebView, it won't respond to it as a UIMenuItem either. You have to detect the event using JavaScript and bridge your JavaScript function to Objective-C. Use the onpaste JavaScript event handler, then do something like what is described here:

<!-- snippet from your HTML string -->
<script type="text/javascript">

    function call_objc_paste(text)
    {
        window.location.href = "fakescheme://" + text;
    }

</script>

<input type="text" onpaste="call_objc_paste(this.value);" />

// Objective-C code:
webView.delegate = self;
[webView loadHTMLString:htmlStr baseURL:nil];

- (BOOL)           webView:(UIWebView *)wv
shouldStartLoadWithRequest:(NSURLRequest *)rq
            navigationType:(UIWebViewNavigationType)navT
{
    NSString *rqStr = rq.URL.absoluteString;
    NSString *scheme = @"fakescheme://";
    if ([rqStr hasPrefix:scheme]) {
        NSString *pastedText = [rqStr substringFromIndex:scheme.length];
        // potentially do somethin with pastedText, then

        return NO;
    }

    // it's not our fake URL scheme, just normal navigation
    return YES;
}
Community
  • 1
  • 1
  • Thanks! :). Is there a way I could do the same for images as well? – vivek241 Aug 19 '13 at 17:48
  • @vivek241 Just out of curiosity, how is it possible to paste an image? Which HTML element is used for that? –  Aug 19 '13 at 17:50
  • I'm looking for a solution that is similar to the native email app on iOS. – vivek241 Aug 19 '13 at 17:52
  • @vivek241 I guess there's no easy/default solution for that. If you look for a code snippet, you may be able to find something. Then try messing around with the event handlers of the element the image is pasted into (it won't be easy if you don't know JavaScript). You could get an image URL or the image data encoded in Base-64 or something. –  Aug 19 '13 at 17:54
  • Is it possible to get the pasted text for a div tag with contenteditable set to true? – vivek241 Mar 19 '14 at 13:03
0

Resurrecting this question for posterity:

Have a look at my answer here: Manipulate paste content in WKWebView the solution uses method Swizzling and can be used for this case too.

Kappe
  • 9,217
  • 2
  • 29
  • 41