Duplicating a VirtualBox Hard Disk on Mac Host

November 5, 2010

I’m running VirtualBox on a Mac OS X host, and I had one .VDI hard disk file that I needed to duplicate into three and use them all at the same time. When I tried to load them all into different VMs inside VirtualBox, I got an error that a hard disk with that UUID was already in use.

Turns out that you can’t just duplicate the hard disk file–you need to use a command called VBoxManage to do it. But it took me a while to find out how to run that command on a Mac.

Here’s what you need to do in a console window:

/Applications/VirtualBox.app/Contents/MacOS/VBoxManage clonevdi path/to/yourold.vdi path/to/vditocreate.vdi

It will probably take a while, and it will only update the progress indicator every 10% or so, so have some patience and you should be set. Once the duplicate is made, just create a new VM in VirtualBox, and choose your new .VDI file.

External CSS and JS in a UIWebView

November 1, 2010

When you’re displaying content in your iPhone app in a UIWebView, it’s helpful to be able to store your JavaScript and CSS in external js and css files. But the way to access these reliably has changed as iOS has matured, and there’s a lot of outdated misinformation about it online. Here’s what worked for me.

By the way, this assumes you’re programmatically creating the content shown in your UIWebView, so this solution wouldn’t work if you’re accessing external web sites. But if you’re doing that, they’ll probably be referencing external CSS and JS anyway. Also, my app doesn’t need to display images in the UIWebView, so I haven’t looked into a solution for displaying local images.

As of iOS 3.0, it appears that a UIWebView can no longer access local files directly. But you can get around this by reading in the contents of the files and then writing them into the HTML of the page you’re going to display. This means you can still store the CSS and JS in their own files, which is much better for readability.

Here’s the code snippet to pull it in: (you may need to copy-paste to see it all)

// load css styles
NSString *cssPath = [[NSBundle mainBundle] pathForResource:@"MyCSS" 
NSData *cssData = [NSData dataWithContentsOfFile:cssPath];  
NSString *cssString = [[NSString alloc] initWithData:cssData

// load js
NSString *jsPath = [[NSBundle mainBundle] pathForResource:@"MyJS" 
NSData *jsData = [NSData dataWithContentsOfFile:jsPath];  
NSString *jsString = [[NSString alloc] initWithData:jsData

// compose full html page
NSString *pageContent =
[NSString stringWithFormat:@"%@%@%@",
 cssString, jsString, actualPageMarkup];

If you try this, the page should display with your CSS, but the JS won’t work. Why? Because, by default Xcode 3.2 thinks your JS files should be compiled, and it doesn’t know how to do it. Instead, what you want is for Xcode to just include the JS files in your bundle, just like it does with the CSS files. To do this, go under Targets in your left-hand “Groups & Files” sidebar, then under your app, then under “Compile Sources.” You should find all your JS files under there. Drag them under “Copy Bundle Resources” instead, rebuild, and the JS should run just fine.