views:

610

answers:

3

I have a very simple Mac Cocoa app that just has a Web View that loads an HTML file with some CSS and JavaScript. I have hooked up the app delegate to this method:

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
  NSString* filePath = [[NSBundle mainBundle] pathForResource: @"index" ofType: @"html"];
  NSURL *url = [NSURL URLWithString: filePath];
  [[self.webView mainFrame] loadHTMLString: [NSString stringWithContentsOfFile: filePath] baseURL: url];
}

The index.html file contains the following:

<html>
  <head>
    <title>Hello, World!</title>
    <link href="style.css" rel="stylesheet" type="text/css" />
    <script type="text/javascript" src="jquery.js"></script>
    <script type="text/javascript">
      jQuery(function($){
        $('h1').fadeOut()
      })
    </script>
  </head>
  <body>
    <h1>Hello, World!</h1>
  </body>
</html>

The style.css file gets loaded correctly, because I set the background to grey in that, so I know it can load other assets from the resource bundle. The javascript code does not get executed. If I open index.html in Safari, the Hello World h1 disappears, as expected. Why doesn't this happen in the app in my WebView? Do I have to do something to enable JavaScript? The box next to JavaScript is checked in Interface Builder.

The code for this is available at http://github.com/pjb3/WebViewApp

+2  A: 

You don't have to do anything to enable JavaScript; it's enabled in the WebView by default. And like you said, you can always check in Interface Builder that the JavaScript checkbox is selected.

What you have to do, though, is make sure that the baseURL you're specifying is correct (since in the html file you're referring to jquery.js with a relative URL using just the filename) and that you've included the jquery.js file into the bundle resources.

The code you posted will result in a nil value for the url variable: +URLWithString: expects a valid URL string (that conforms to RFC 2396) as the argument (which the filesystem path you're providing is not). What you want is +fileURLWithPath:, and you also need to use the filesystem path of the directory where index.html and jquery.js reside, which you can get by removing the filename from the path you've got (using NSString's -stringByDeletingLastPathComponent:). Here's how you get the correct baseURL:

NSURL *url = [NSURL fileURLWithPath:[filePath stringByDeletingLastPathComponent]];
hasseg
I've made these updates, which make sense, but it still doesn't seem to work. You can see the code at http://github.com/pjb3/WebViewApp
pjb3
Ah, I figured it out. I didn't know what you meant by "included the jquery.js file into the bundle resources". I dragged the .js files that were in the resources folder into the "Copy Bundle Resources" um...thing :), under WebViewApp in Targets. All is well now, thank you!
pjb3
A: 

In addition to what hasseg said: Why not use this to load the file instead?

NSURL *url = [NSURL fileURLWithPath:filePath];
[self.webView setMainFrameURL:url];
Peter Hosey
A: 

Just a quick update for anyone still struggling with this... I was having the exact same problem where I had an html page with the prototype.js library loaded in the <head></head> section of the page. But the library was not being loaded when I opened the same page within a WebView in a Cocoa app. Actually, no script files being loaded (even my own) seemed to work in the WebView.

I downloaded the above github code that from the link pjb3 provided, hoping that maybe he'd found a fix and updated it. No such luck. It still had the same problems.

And then I decided to look in the package contents of the compiled app (so that would be WebViewApp/Contents/Resources off of the build/Debug or build/Release directory where XCode has compiled your app)... Oho! The javascript files he had put in the Resources section of the XCode project weren't actually being copied over to the built app's Resources directory. I looked in my project and it was the same problem. The fix? Simply drag any of the scripts you've added into the "Copy Bundle Resources" section of your app target in XCode and voila, they'll be there (and things will actually work!).

I thought everything that you put in Resources was getting copied over automagically, but I guess it wasn't. And unfortunately with a WebView, unless you do a bit of work, you don't have all the great web debugging stuff that Firefox or Safari would have that would have made this problem easier to find. So, when in doubt, check if your actual compiled app has the resources it needs under its Resources directory (is this maybe the programmer's version of "Is it plugged in?"?). This took me a lot of head scratching and my only consolation for the lost hours is that I can maybe save some other folks from the same. Happy coding!

David Ackerman
The groups in the group tree, such as “Resources”, are nothing more than organizational tools. You can put resources in the Classes group and source files in the Resources group and it makes no difference to what happens at build time. The build phases (e.g., “Copy Bundle Resources”) are what happens at build time. Also, it's Xcode with a lowercase c, not XCode.
Peter Hosey