When it comes to writing hybrid mobile apps on iOS today, you usually get to pick between two extremes: 1) primarily use web development technologies and host them in an enhanced WebView (such as PhoneGap), or 2) write a fundamentally native application (CocoaTouch, MonoTouch) and sprinkle in WebViews from time to time and write your own ad hoc gateway between the WebView and your native code.
Today, we’re going to talk about a way to embed a Cordova1 web view in a MonoTouch application. To get a high-level overview of what we’re going to be doing, you can look at the documentation for the Xcode and CocoaTouch version of this process.
Prerequisites
FIrst things first. You’ll need to clone both of the following repositories from GitHub:
- https://github.com/sblom/monotouch-bindings/ – The MonoTouch-bindings repository is an all-around fantastic resource for linking against, and even discovering, many 3rd party services and applications.
- https://github.com/apache/incubator-cordova-ios/ – This is a GitHub-based clone of the, IMHO, slightly less convenient Apache Cordova repo.
Implementation steps
I believe you’ll find it easiest to follow along with these steps if you at least skim through the Screencast that I’ve embedded below.
- Create a new Tabbed Application project in MonoDevelop.
- In your Project References, add a Reference to monotouch-bindings/Cordova/Binding/Cordova.dll (monotouch-bindings is one of the repos that you cloned during the prereqs step above).
- Use Cordova’s create tool in incubator-cordova-ios/bin to create a Cordova project (for example: ./create ~/src/xamarin/cordova-stub com.greenesse.cordova-stub CordovaStub)
- Copy Cordova.plist from your freshly created Cordova project’s cordova-stub/CordovaStub folder into the root of your MonoDevelop project. Note: be sure to set its build action to "Content" in MonoDevelop.
- Copy the entire contents of cordova-stub/www to a www folder in your MonoDevelop project. (I ran cp -r www ../CordovaTest/www from within the cordova-stub folder.)
- Be sure to set the build action for all of the files within your project’s www folder to "Content". I don’t like using multi-select in MonoDevelop for this, especially when there are crazy folder nestings and more than a dozen files, so I run the one-liner find www | awk ‘{ print " <Content Include=\"" $0 "\" />" }’ to generate a bunch of lines for me to copy and paste into my .csproj file.
- In Interface Builder, delete the sample text from SecondViewControl.xib, and add a single View that takes up all of the space below the application’s toolbar.
- Wire the freshly added view to an outlet called bounds. Save your XIB file and return to MonoDevelop.
- Make the following code changes to SecondViewController.cs:
Voilà!
With that, you should be able to compile and run the application in the iOS Simulator, as well as on actual iOS hardware. You’ll notice that the second tab in the demo application does, indeed, now host a Cordova web view. You can add multiple CDVViewControllers, each pointing to a different WwwFolderPath and/or StartPage. The sky’s the limit!
Future exploration
Additional topics that we could explore in the future include:
- Writing Cordova plug-ins entirely in MonoTouch.
- Hosting a gallery of Cordova samples behind a native ListView.
Do you want to explore any of those? Do you have any other things we should dive deeper into?
Screencast
Embedding Cordova (PhoneGap) in a MonoTouch app from Scott Blomquist on Vimeo.
- If you’re like me, when you see the word “Cordova”, you should think “PhoneGap”. The name Cordova refers to the Apache open source project born from Nitobi’s PhoneGap. When Adobe acquired Nitobi, they kept PhoneGap as a trademark for their own value-added products and services that are built around the Cordova core. [↩]
3 Comments
Hey Scott, Love the article. I’m currently working on an app that is a combination of Cordova and Monotouch, so this has been immensely helpful. Unfortunately when I tried to make the Cordova monotouch binding, and then reference that from my Project, I get an NSInvaidArgumentException unregognized selector sent to instance when I attempt to create an instance of CDVViewController. Any idea how I can get around that?
I’ve posted my issue as a StackOverflow question, in case other people are encountering similar issues.
Apparently I forgot to attach the URL to the last comment, and I can’t edit my comment, so here it is http://stackoverflow.com/questions/15256719/trouble-with-monotouch-bindings-to-cordova-nsinvalidargumentexception
2 Trackbacks
[...] found a guide that describes this scenario, so I know that this is possible, and the author has added a Cordova Binding to their fork of the [...]
[...] found a guide that describes this scenario, so I know that this is possible, and the author has added a Cordova Binding to their fork of the [...]