Calling Objective-C from Javascript

Discussion in 'Mac Programming' started by Blakeasd, Mar 15, 2014.

  1. Blakeasd macrumors 6502a

    Joined:
    Dec 29, 2009
    #1
    I am fooling around with using Javascript to call Objective-C and I can't get this seemingly simple task to work. I'd like to launch a simple NSAlert and write an NSLog, but I cannot get these results. Here is my AppDelegate implementation:

    Code:
    
    -(void)awakeFromNib{
        [self.webView setDrawsBackground:NO];
      
        NSString *resourcesPath = [[NSBundle mainBundle] resourcePath];
        NSString *htmlPath = [resourcesPath stringByAppendingString:@"/index.html"];
        [[self.webView mainFrame] loadRequest:[NSURLRequest requestWithURL:[NSURL fileURLWithPath:htmlPath]]];
        
        
        [[self.webView windowScriptObject] setValue:self forKey:@"AppDelegate"];
    }
    
    
    - (void)showMessage:(NSString *)message
    {  
        NSRunAlertPanel(@"Message from JavaScript", message, nil, nil, nil);
        NSLog(@"foo");
    }
    
    and the html:

    Code:
    <!DOCTYPE html>
    
    <html>
    
    <body>
    
    
    <input id="message_button" type="button" value="Show Message" onClick="window.AppDelegate.showMessage_('Hello there...');" />
    
    
    </body>
    
    </html>
    
    
    I get one button like I expect, but clicking it has no effect. Interestingly enough, adding a simple alert instead of my Objective-C code doesn't work either. It does however work in Safari when I run the exact same HTML code in my browser.

    Why won't things work in my WebView?
     
  2. mrichmon, Mar 15, 2014
    Last edited: Mar 15, 2014

    mrichmon macrumors 6502a

    Joined:
    Jun 17, 2003
    #2
    Sounds like Javascript is disabled in WebView. (You can check just by rendering straight HTML into the WebView.)

    On Andriod, the details are explained on the following page with instructions on how to enable Javascript in the Android WebView:

    http://developer.android.com/guide/webapps/webview.html#UsingJavaScript

    This might provide some ideas.

    http://will.thimbleby.net/script/

    On terminology, your example is "calling Javascript from Objective-C". Not calling "Objective-C from Javascript".
     
  3. ArtOfWarfare, Mar 15, 2014
    Last edited: Mar 15, 2014

    ArtOfWarfare macrumors 604

    ArtOfWarfare

    Joined:
    Nov 26, 2007
    #3
    No, he's right. He wants a button press in a web view (JS) to call some Obj-C code.

    I found this Apple Developer Document titled something that looks super helpful for you:

    https://developer.apple.com/library/mac/documentation/appleapplications/Conceptual/SafariJSProgTopics/Tasks/ObjCFromJavaScript.html
     
  4. Blakeasd thread starter macrumors 6502a

    Joined:
    Dec 29, 2009
    #4
    I've checked and Javascript is enabled for my WebView. I've done some more tests and found that some Javascript code will work while other Javascript code does not.

    Thanks! But I've already read that.

    This HTML code's Javascript will work:

    Code:
    <!DOCTYPE html>
    <html>
    <body>
    
    <h1>My First JavaScript</h1>
    <p>Click the button to display the date.</p>
    <p id="demo"></p>
    
    <button type="button" onclick="myFunction()">Try it</button>
    
    <script>
    function myFunction()
    {
    document.getElementById("demo").innerHTML = Date();
    }
    </script>
    
    </body>
    </html> 
    
    
    this HTML code's Javascript will not:

    Code:
    <!DOCTYPE html>
    <html>
    <body>
    
    <p>Click the button to display an alert box.</p>
    
    <button onclick="myFunction()">Try it</button>
    
    <script>
    function myFunction()
    {
    alert("I am an alert box!");
    }
    </script>
    
    </body>
    </html>
    
    
    Both of these examples work perfectly in Safari, though. :confused:
     
  5. ArtOfWarfare macrumors 604

    ArtOfWarfare

    Joined:
    Nov 26, 2007
    #5
    How could alert possibly work in a WebView? If you want to implement something like that, send a message to your Obj-C code from the JavaScript and produce an NSAlert with the contents of the message.
     
  6. Blakeasd thread starter macrumors 6502a

    Joined:
    Dec 29, 2009
    #6
    alert(); isn't Objective-C . This works perfectly fine in an example app I saw using a WebView.
    After redoing my app it works for some reason.
     
  7. chown33 macrumors 604

    Joined:
    Aug 9, 2009
    #7
    You have the perfect starting point to make incremental changes.

    Start with the one that doesn't work. One line at a time, change that one line to whatever is in the one that works. If it still doesn't work, choose the next line to change. Continue until it starts working.

    You can do it in reverse, too. Change one line of the working one to be whatever line is in the not-working one. Repeat until it doesn't work.

    In either case, the line that changes things (not-working to working, or vice versa) is the line to focus on. Go to the original working one and change only that line. What happens? Or go to the original non-working one and change only that line. What happens?

    Post your results, specifically the line that caused the non-working one to work, or the working one to not work. Post complete code of the before and after.


    Making incremental changes is a basic debugging skill. If you've never used it before, this is a good opportunity to practice it.
     
  8. ArtOfWarfare macrumors 604

    ArtOfWarfare

    Joined:
    Nov 26, 2007
    #8
    Sooo slow. Do a binary search - it'll be take a tiny fraction of the time. Change half the program to match its counterpart. Worst case will be log(n) vs n steps where n is the number of lines that differ between the two.
     
  9. Terminated macrumors newbie

    Joined:
    Mar 18, 2014
    #9
    The alert javascript function doesn't work on a basic WebView. If you have seen a WebView where it works, it's likely that such WebView is using a WebUIDelegate that implements the method "webView:runJavaScriptAlertPanelWithMessage:initiatedByFrame:".

    Concerning the code you originally posted, my impression is that you have forgotten to override "isSelectorExcludedFromWebScript:". For security reasons, all methods are excluded by default even if you have registered the class with a WebScriptObject. In your case you should add this to your AppDelegate:

    Code:
    + (BOOL)isSelectorExcludedFromWebScript:(SEL)aSelector
    {
        if(aSelector==@selector(showMessage:))
            return NO;
        return YES;
    }
    
     

Share This Page