Mac • 54:15
WebKit lets you build Mac OS X applications that combine the rich user experience of Cocoa applications with dynamic web content. Walk through the development process of building an application that uses WebKit and learn design principles for making your application extensible for new features or updated content. See how to maintain a uniform look and feel in hybrid applications and discover the best practices for performance and error handling.
Speakers: Mike Lopp, Tony Kinnis, Gregor Purdy, Ryan Orr
Unlisted on Apple Developer site
Transcript
This transcript has potential transcription errors. We are working on an improved version.
Michael: Good morning. My name’s Michael Lopp and it’s a pleasure to be back here at WWDC talking with you about leveraging web content in Max OS X applications with WebKit. As I said, my name’s Michael Lopp, I run the online store. And this is what the online store looks like, in case you haven’t had a chance to see it. This is web content and let’s go ahead and leverage it. There; what we’re going to do here, the story, the story behind this presentation starts with Sting, if you can believe it or not.
This is a feature that’s in GarageBand that we announced in MacWorld called Artist Lessons. And last summer we came, GarageBand team came to us and they said, hey we want to do this feature called Artist Lessons. And what it was, if you guys don’t know is, this is an amazing feature inside of GarageBand where Sting and other artists actually teach you how to play these songs. And it’s beautiful high, high production quality, gorgeous applications.
Now Online Store Music Lessons, what’s going on here? What they wanted to do, they have some very successful requirements, they wanted, these files are really big. They’re like half a gig to a gig and a half in size. And that means they weren’t going to get them all on the High Life DVD. The other thing is they want to charge for them, obviously.
And the other thing was they were going to constantly have new ones. The fourth thing was what they wanted to do is they actually wanted to embed the experience of merchandising and browsing inside of the application. They wanted to not have it be a jarring jump into another application experience.
And so that’s what we did for them. This is the Lesson Store. And this is the media browser inside of GarageBand. And if we’ve done our job well, you will not know that everything over there on the right, everything in the black box is the same thing as you were seeing on that first slide that I told you, showed you, the white page.
That’s the store. We embedded it. We did some amazing things with WebKit, and we did some amazing technology that we guys want to talk about today. The nice thing about this is you stay inside of GarageBand the entire time. You’re purchasing, you’re downloading, everything happens inside of GarageBand. It’s a really beautiful user experience. And the reason, what we’re going to talk about today is actually what we learned as part of this process of embedding this store inside of it.
What’s happening that’s really cool is that platforms are merging. On one side you’ve got Cocoa; on the other side you’ve got the Web. And what we’re able to do, thanks to a lot of technologies that we’re, Apple’s producing, is you can start to pick and choose the respective parts to build something new. The GarageBand browser is Cocoa, it’s gorgeous, it’s beautiful, and it’s the store all working together.
And again, you probably will never notice when you’re coming, or when you’re leaving, or coming inside of it. The idea that we want to talk about, what we want to get the creative juices flowing is around what are these new things we’re going to build with these effectively mash ups.
What are the things that you guys are going to build using all this technology? And we’re going to spend some time doing a technical [inaudible], walking through the lessons that we had, that we learned, so you guys can start thinking about it. One of the things I want to address before we get started is the idea of web applications.
If I told you 5 years ago that I was going to build a web app, the first thing that you would have said would be what happens when I’m on the plane? What happens when I am away from the internet? The fact of the matter is you’re not really away from the internet any more. How many of you have an internet connection on you right now?
A show of hands. That’s everybody. There’s always, and it’s around. But as you’ll see as part of this, the technologies we’re going to talk about today, they degrade nicely. And when you get WebKit and Cocoa working together, they can actually protect each other and put together a great experience for degrading when there is no internet connection. The other thing obviously is their database API. You can build these technologies, you can build applications where the content’s stored off line and used at a later date.
Anyway, enough of me. Let’s bring the people up here that would do actual work. I’m going to bring Tony Kinnis up, he’s the Engineering Manager for the store. Start with a technical overview. Then, then we’re going to bring up Gregor Purdy, who is going to walk you through our example app that we have a lot of fun with, and you see the Cocoa side and bridging Cocoa or WebKit, JavaScript, all that fun. And then we’ll go on the other side, talk a little bit about the web and show you the app that we’ve actually built from the WebKit side of the world. So with that I’d like to bring Tony Kinnis up and we’ll get started.
[Tony Kinnis]
Thank you Michael. As Michael said, today I want to, if I can get to the other side of the stage, give you a bit of a technical overview. And as part of that technical overview I want to cover these three topics. I want to talk a little bit about why these platforms are merging and what we stand to gain from that.
I also want to sort of take you through some of the things you can do with WebKit, specifically as it relates to Cocoa. And then at the end I’d like to go through some design considerations about building these hybrid applications. So first, you know, why are we merging desktop and web platforms, and you know, who cares?
Well I think as far as who cares goes, it’s people who want to sort of take advantage of a lot of benefits. And some of the benefits we want are things that Cocoa applications or desktop applications give us. Things like interacting with your local files system. That’s something you take for granted as a Cocoa developer. But as a web developer it’s not something you can really do.
Additionally we want to communicate with peripherals. You know, the, you can interact with Bluetooth, you can interact with your iSight camera, USB, FireWire devices, etc. Also we want access to the system information. This could be things like, you know, what’s the preference of language for your user? What currency format do they choose to use?
What kind of Mac or operating system are they running? Things like that. And, you know, as we were saying, you know, internet’s everywhere, but also desktop applications allow you to function without internet app, without internet. So you don’t have to launch your browser and connect, you can just launch something like iPhoto, browse your photos; make edits, and things like that. And you don’t need internet to do that.
And also you probably want to interact with other applications on the desktop. You might develop a suite of applications that, you know, you produce, and you, and you get out there in the world. And you want them to be able to communicate with each other, share information, and things of that nature.
We also want the benefits of Web Platforms. And Web Platform can do things for us like last-used, HTML, CSS, and JavaScript to display dynamic and fluid content. You render a page, you take the corner of it, you drag it to the other end of the screen, everything reflows, the text realigns, images move around.
And that’s pretty handy, and it doesn’t take a lot of effort to make that work. And it’s great for producing really rich content, especially dynamic content. Also, you know, with Web Platforms we’re able to easily deploy changes for our users. We can put a new function, new operations, new pages, what have you, up on our servers. Users don’t really know that’s happening. They come back on and visit your site.
Everything’s there, and they’re like, oh surprise, I got new stuff. And then, you know, web development’s nice, because it’s mostly cross platform. You don’t really have to worry about a new build of the operating system and things like that. There are considerations for things like, you know, am I using a certain version of browser that may provide additional functionality separate from the version that you originally built for, but that’s pretty minor concern, easily worked around. Also, you want to take advantage of shorter release cycles.
That’s something we do a lot in the Web world. You know, with the Cocoa applications, you know, you take your time, you build it, you send out a software update. It’s not something you normally see where you get a software update every week. However, web content can be changed daily, hourly, weekly.
And users are not interrupted by that. So what we really want is we want it all. We want it all together one seamless experience taking advantage of all of these features, and we’re calling these hybrid applications. And specifically hybrid applications now allow you do things like have WebViews that can interact with local file systems. You can have an HTML input button that, you know, calls through the Cocoa bridge and invokes iSight and takes a picture.
Or, you know interacts with a device, which is connected via Bluetooth. Your web views can also interact with other desktop applications. You can have an input button, again, as an example, that you can click and goes, again goes to the Cocoa bridge and sort of take advantage of the other applications that may be installed on your system. And these may be other applications that you’ve developed, that your companies produced that normally share information.
And now your web views can have that too. You’re not limited by that. Your desktop applications, now this hybrid application, can also have fresh content. You might have help pages that are maintained regularly that are easily accessible for your app. You might also have integrative web forums; you might have various things like that, that you publish daily or weekly.
And when your users launch your application all that information’s immediately available in a very seamless way, they never have to leave the application to get it. You can now deploy new features without taking a software update. So anything that you publish through a WebView, you know, can immediately manifest in the application without your users having to take a software update.
And that’s pretty powerful concept, because, you know, software updates, you can’t guarantee every user’s going to take that, or you may not be able to guarantee every users going to take a software update. So this is a nice way of deploying new features to your users without them having to opt in to it, it’s a, they get it for free. Commerce opportunities is another thing that these hybrid applications can make available to you. Let’s say you’re a game developer and you’re writing a really beautiful game, and as part of that you have MacPacs [phonetic] and levels, or whatever that you’d like to distribute.
Wouldn’t it be nice if while playing the game you could just go through an experience where you can browse MacPacs, purchase them, and have them immediately installed without ever actually leaving the game? And that’s a pretty powerful idea, because you know, if you think about the user experience of, hey I’d like to buy a MacPacs, okay, launch your browser, go through a process, download a file, open finder, click the installer, have it installed, and relaunch the game. That’s a, an inferior experience compared to what you can achieve with a hybrid application. And then lastly as we were saying, we can take advantage of this dynamic layout in fluid UI.
You know, you can have your application resized, easily draw tables of information, and style them in very beautiful ways. Really power of CSS and HTML and JavaScript these days is pretty significant, and you can see later on we’ll show you a couple of little things you can do that give you a really nice experience.
So with that we’ve talked about some of the benefits, some of the things you can do with the WebKit, Cocoa experience. Now I want to sort of introduce you to some of the things that you can do with WebKit via Objective-C. These are things that you probably will make use of in your applications. So one of the key things you will be able to do is monitor activity.
And you may have in your WebView a button, or a link, or something of that nature that will respond to user interaction, and then request Window.open in some URL. And with that, with Objective-C you’re able to, first, assign a delegate and intercept that information and decide, well, do I want to open that in a custom Cocoa view of my choosing? One that I’ve built myself?
Or do I just want to launch the browser externally and have that open up. And sort of exit my app at that point. You’ll have the choice to do those sort of things. You, as things are happening in your application you might want to report status back to your users, you know, have the pages loaded yet?
That’s easily accessible. Was there an error loading the page for some reason? Also you can get at that pretty easily. And likewise, all of the things that load on those pages, like CSS, JavaScript, and Images, you can actually track all that information and sort of know whether they’ve done loading or still loading, and whether or not they error. Managing navigation is going to be an important aspect to this. And you can do things like maintain a WebKit’s backward and forward list.
This is basically the history of the single WebView. And by doing that you’re able to hook up controls, allow you to easily navigate forward and backward. These are the same kind of controls you hook up at a regular browser, like Safari’s forward and back buttons. So you can hook them up any way you see fit in your own applications. Or use user events and some sort of interaction with the user to decide to move forward and backward automatically without the user having to click those buttons. You have control over that.
The other aspect of this is that you want it to perform well. And with Web Pages one of the ways to get performance is to let the browser cache, cache the data, cache the resources. And that’s a pretty common feature. And with WebKit you’re able to control the size of these caches and the capacity of them. And additionally you can turn it off all together.
If you wanted to not have any cache content, and always have fresh resolves that’s easy to do. But you probably want to use the caching, because if the user’s already visited the page it’ll load much quicker for them the second time. With Safari you can do something where you can see the history of all the URLs you visited and how long ago you visited. WebKit will allow you to do that. Basically you just register a history object, and then that’ll give you a linear storage of all of the places you visited and how long ago you visited them. You may want to display that information to your users for some reason.
And you can track that on a single WebView over time, over, you know, subsequent runs of the application. Or you could have it available, shared throughout all WebViews in your application, so you can have all your history sort of go into one place. The other thing you can do, you might want to do is decline the ability for certain URLs to load. So if you’re building a WebView inside of your application, you might want to put restrictions then to say, yeah, I only want URLs to load from my domain.
So mycompany.com, for example. You can easily do that, you register [inaudible] you can sort of veto loading of pages by simply checking the domain that’s being loaded, the URL, the path, the parameters, the IP address. You have access to all that information, and you can decline based on whatever conditions you want.
[ silence ]
There may be cases where you want to allow users to edit the content in the pages. Let’s say that you’re writing your own web log tool, some integrated thing that has a web log view. And you want to provide styling, and input, and things like that.
You could actually have them type directly into a document that gives you the WYSIWYG experience. You just set the WebView and said editable mode, and then you just focus the cursor in there and start typing. And it’ll allow you to type, and drag and drop images around, things of that nature.
And because you’re allowed to edit the objects directly with DOM in a WYSIWYG manner, you might want to be able to save that content and reload it later. You might want to save it to the local disk. You might want to save it back to the remote server. Additionally you can reload that content from disk or from a remote server.
And as I was saying, you can have these WYSIWYG experiences. One of the things you might do is have a menu option, say insert a table here a 3 by 3, you know 3 rows, 3 columns. You can easily inject into the DOM for that WebView a table of cells, table rows and columns, and then have that show up in the WYSIWYG manner, and people can just type into it. Another nice feature is managing an application cache. So we were talking about, you know, broadband is pretty pervasive these days, but you may not always have an, an internet connection.
And when you don’t, WebKit provides a feature called Application Cache for off line applications. And ultimately it just boils down to providing a manifest file that says, in addition to my page being saved to disk, here are all the other resources I would like to save to disk as well. So these are things like CSS files, JavaScript, images and things of that nature you want to make available.
So that if a request is made for that page again, and you happen to be offline, it’ll load it from your local cache. Now that’s handy, because possibly your WebViews don’t need constant interaction with the web server. So, with that you can have an application run even without internet connection. And to make that even more powerful, there’s a feature where you can store key value pairs locally as well.
So you don’t have to have all your state persisted on the server, you can actually store key value pairs both from a, what’s called a local storage, which is the current WebView, or a session storage, which is across WebViews. And then basically you store that data. And then when your application loads off line it’ll have all that data available to it.
And it can keep adding to that. And then you could have it be smart enough to know that when it comes back online it could push those results back to your server if needed. And even more powerful than that, you have flexibility to use a full relational database on the client’s side. It’s a SQL live database, there’s a full JavaScript API to allow you to create tables, insert rows, delete rows, and run queries.
Again, making the off line option even more appetizing. Another powerful, a very, very powerful feature is bridging functionality. And let’s say, for example, that you have some API and JavaScript in your WebView, you’re in a function that does a lot of different things, it interacts with the controls and what not, you can actually invoke that from Objective-C. So you can easily have a menu option or something in Cocoa that calls through to the WebView and invokes functions and even passes data across this bridge.
And you can go the other direction. So you can export functions from Cocoa to JavaScript that allows you to call out. So you can do things like call out NS to have iSight brought up and, or you can call out and maybe communicate through a Bluetooth device. You can’t do that directly from JavaScript, but you can write functions that you export via your Cocoa interface to the bridge, then you can have JavaScript interact with that.
So after we, you know, we talked about benefits and the kinds of things you can do, some of the things you can do with WebKit, there are some things you should probably consider before you start writing your application. These are some of the things that we thought about when we were working on the GarageBand integration for the Lesson Store. And some of them may apply to you.
We want to share some of those with you. Specifically, you want to try to minimize the need for your users to take updates. It can get a bit frustrating if every time you rev, you rev your web content your users have to take a software update to go along with it. Though that’s not normally true, but depending on how you do things like maintain backward compatibility in your API, especially those bridged functions, you know, you could end up having JavaScript that has requirements that your current version that your desktop user’s using doesn’t match up with.
So that’s pretty avoidable. You can, you know, export information about the version of the app you’re interacting with, and have your JavaScript to be smart enough to sort of fall back gracefully, and sort of use the methods that it accessible. Also you want to try to anticipate the future when designing these interfaces. Yeah, no one can predict the future, but you know, think out 3 months, 6 months, a year, I don’t know how far out you can think about this.
But think hard about those Cocoa APIs that you’re exporting. Because if you think you want to add a feature, but you’re not ready to build it yet, you know. If you provide that in the desktop application when you ship it, then later when the web app, you know, is ready to be built, or that feature’s ready to be exported, you can simply just hook up to the API you’ve already exported.
And then all of a sudden your uses have a, a new feature that they didn’t maybe know about. Then this is pretty handy, because as you’ll see in one of our examples, we, we are exporting more data than we might need, and we can later show you how to take advantage of that.
Also if interconnectivity is an issue, as I was saying before, you know, think about using things like off line application cache, client side storage, or at least just provide your users with good messaging about when you’re not connected to the internet, what features they can use or not use about your application.
The more seamless you make it for your users the better it’s going to be. But, you know, it’s something you need to consider, especially when, you know, you’re relying on it. And another one I think is pretty important here is reduce number of URLs you bake into your application.
So let’s say you have, you know, 5 or 6 different WebViews that get content from different places, you really want to be careful about putting those URLs directly into your resources and shipping with your application. Because, let’s say today you have help with, you know, it’s some URL. And then later you decide, no I want a help to come from a completely different source, completely different location, well are you going to send a software update for that? You, you would have to if you shipped it, or theoretically do some server side redirection.
But you can make it simpler. You can do something where you bake 1 URL into your application. And when your application launches it could go off and fetch, wonder [phonetic] URL configuration for your application, which has a bunch of other URLs you’re going to use. So that may be an interesting way for your to overcome things like this, where you have 1 URL that says get my configuration for my application.
And what comes down with that is a series of, you know, 4, 5, 8, 10 URLs that are going to be used for other WebViews. And you can store, you can, you know, you can decide to cache that information for minutes, hours, days, or weeks, or just have it fresh all the time. So any ways, those are some of the things that we considered. There are probably more finer details specific to your application than your use cases.
But these are some of the things that we thought about. So with that I’d like to bring up Gregor Purdy, Engineer-at-Large. He’s going to talk about a specific application and show you how to do some of the things that I was just over viewing, specific API and things in Cocoa and JavaScript.
[Gregor Purdy]
[ silence ]
So what I’m going to do is walk you through a, brief demo. You’ll see a little bit more of the demo later on from Ryan. But I’ll walk you through just enough to kind of set the stage for context. You can see the code samples that we’re going to show you will make some sense. And after that I’ll take you through, basically three of the operations that you need to do. The first one when the application is starting up, how to get that initial content loaded into your WebView.
And the second one will be how do you do passing, maybe some custom data object that you have, that you’ve gotten on your Cocoa side, over to the JavaScript side, and let it do something interesting with it. And then finally I’ll take you through some example code that shows how you pick up an event, let’s say a user clicks something in the WebView.
And because of that you want to then call across to the Cocoa side, across the bridge, and have something interesting happen that you couldn’t have otherwise done in a pure web application. So with that I’ll switch you over to the demo machine and just give you a quick view of the application. Good.
[ silence ]
So this is a simple little example application that we built for the session today. It may look familiar to some of you. There’s a lot of applications out there that are like this. This is actually a Twitter client. It’s patterned after one called Tweety. There’s many out there. But we’d like to than Warren for allowing us to kind of rip on his UI here a little bit. But we took his as a pattern, and then we had some other ideas of things that we wanted to play around with in the application.
And what you can see here is content where we replaced, and you can see these little iTunes icons here. A lot of times when somebody’s sending out a status update in Twitter they may use a long URL that they want to provide a link to. And they’ll run it through a URL shortening service to make it bit.ly, or something like that to make a short version, and then paste that into the status update. And so what this application is doing is actually contacting 3 different web services from the, over the internet. So the first one is the Twitter API. And the second one is bit.ly, again there’s many other shortening services out there, but that’s the one that we’re demoing.
And then finally iTunes affiliates API is out there, and we’re using that to fetch back information. If we detected the URL happens to be an iTunes URL, and we’ve made it so that if you click on that it pops right into iTunes without having to pop up a separate browser window and do a redirect, which you may have seen if you’ve ever clicked on an iTunes link in some web page somewhere. And so what I’m going to do is take you though the pieces of code that it takes to make an application do this in a hybrid fashion. Back to slides.
So this is a picture that I’m going to use a couple of different places in these slides to sort of, you know, set the context for where we are. And across the top you can see, as I just talked about a minute ago, a representation of the Twitter API, the Bit.ly API, and then the iTunes affiliates API.
Here in the middle is the application controller, like any good Cocoa application we’ve got an app controller. Obviously we have some other classes in there doing other things, but that’ll represent kind of the core business logic of the app. And the little orange box we’re going to use to represent, in this case AlbumInfo.
As you might imagine we’ve got a piece of custom data to represent the status update itself, and maybe an artist information, or even a track information. But the examples I’m going to show is AlbumInfo. And that’s the data that we got back and processed from the iTunes API. Also, as you might expect, we’re going to have some web content, right, HTML, CSS, and JavaScript. And finally, for a demo application we’ve got this iTunes class that we wrote that does some bridging to pop up the, to pop up the iTunes directly right from the application.
So let’s take a look at some of that code. But before we do that let’s talk about, well what tools would you use to do this hybrid application development? The good news, for many of you, is that you use the same tools you’re used to in Cocoa. Right? You use Interface Builder, and Xcode. And you can use Xcode even for the web content as well, if you’re comfortable with that, or if you’ve got some other tool that you like to use, some special purpose tool for editing web content, that’s fine too.
And of course, we’re going to be using the, the WebKit and the web content itself. So let’s look at the first step. So the application is now started up, the interface has been unloaded from the Interface Builder file. And Cocoa is going to call you back and give you a chance to do any final set up that you want to do. And what we want to do is make our interface load up kind of an empty bit of content in our case. In your case it might be something richer that it first loads up.
So we’re going to talk about this piece right here where the application controller is talking to the WebView and telling it to load content. Actually turns out, this is pretty simple to do. Here’s an example in the awakeFromNIB method in the application controller. And really all we’re doing, the first few lines are just creating the NSURLRequest that we want to use to refer to the URL where we stored our content out on the server.
You can store content locally on the disk if you want. You can generate content programmatically. In our case we put it out on Apache Server. And you can see they have some arguments in here about the caching policy, kind of like what Tony was talking about, some more advanced versions of that.
But here’s a simple version of that. And the time out intervals. The main line of code here, though really is this one where we ask our WebView, which is just an outlet that we put in the, in the application controller. And we just ask it for the mainframe, and tell the mainframe to load that request. Once we do that the WebView itself is going to fetch the HTML, it’s going to look and see that there’s images, or CSS, or JavaScript’s that are referenced and pull it all in.
Just like would happen if somebody had hit that URL from a browser. So let’s talk about the second step. The second step is, great, now the UR, the UI’s all loaded up, and, you know, we’ve done some interesting things in our application, and we’d like to display rich web data in the app.
[ silence ]
So what we’re going to talk about is data coming from these web APIs. Right? We can call all different kinds of web APIs from one Cocoa app. There’s no securities manager blocking us from crossing domains or anything like that. And when all the data’s brought together, our application logic, we can create custom objects; we can pass them through the bridge, and have them show up in the window.
So let’s look at some of that code. So the first thing that we’re going to need is to know about the WebScripting informal protocol. So the informal protocol in Objective-C, if you’re not familiar with that, is, it’s a protocol that’s defined in the API, but you don’t explicitly use that in your source code from an inheritance perspective. You just implement the methods and the right magic happens in, in the framework.
So there’s a couple of methods we’re going to show today on how you can kind of control that bridge and make sure that the data that you want accessible in JavaScript is accessible. And then the other thing we want to show is how do you take an object, where you’ve got like that, and then pass it across and it calls the JavaScript. So let’s look at that AlbumInfo object that we were talking about at the beginning. So the AlbumInfo, there’s actually a lot more data available over the iTunes APIs. I’m just showing a few pieces here.
But the actual object in the application is a lot bigger, there’s a lot more data. But as you can see we got an albumID, you might imagine we could use that to refer to this album when we call out to iTunes. And we got some interesting information here we could display. But this is just your basic Objective-C class. Nothing particularly special about it.
Let’s look at the implementation side then. On the implementation side I’m not showing much here, because there’s not much to it. Objective-C 2.0 you would synthesize all of those attributes that we just declared in the header. And the only bit here that’s new and interesting is this method here, is key excluded from WebScript? It’s kind of a mouthful.
But basically what’s going on here is, for security reasons, the default mode for the JavaScript bridge is that nothing on the JavaScript side can access anything on the Cocoa side, or the Objective-C side. Its all default deny. And so what we’re doing here is implementing this method that the bridge is going to call automatically. And it’s going to call us and ask us, hey, is this key, albumID is in, in this case; is this key excluded from WebScript?
And if we return no, don’t exclude it, then that means it will allow the JavaScript to accept, and in this case, the albumID activated that data object. So really all we have to do is put a little if ladder in here that implements returning no for each of the properties that object that we want JavaScript to access. So it might be 3, 4, 5, 10, whatever, it’s very simple code. And at the bottom we just always return yes to exclude anything else.
[ silence ]
Now that we’ve done that there’s only a few lines of code at the call site where you actually want to call into the WebView and make something happen on the JavaScript side. The first line here, you can see, is just doing something to acquire this AlbumInfo object, and getting the info based on the albumIDs.
Behind the scenes you can imagine that calling the iTunes APIs. The second thing is, if we have any arguments to the call that we’re going to make, we need to put them in an array. So here you can see we’re saying NSArray, array with objects, and giving that info object that we’ve got.
And then the last 2 lines of code, really the last ones the, the meat of it, is telling the WebView, hey give me your web window script object, and then saying to that, call WebScript method with arguments. So we pass in addAlbum in quotes, that’s the JavaScript message we want to call, and we pass in arguments array. What does that look like on the JavaScript side?
In the JavaScript it looks just like any other regular JavaScript that you or your friends who write JavaScript might have written. Right? Function out album, it’s got an argument called info. And in the body of it it’s doing some DOM manipulations. And you can see in the orange there, info.albumIDs.
That’s standard JavaScript notation, and it’s actually calling across the bridge. It’s being checked if it’s allowed. It’s allowed, so it’s grabbing that piece of data, bridging it across. And that’s really all there is to passing data from the Cocoa Objective-C side in to the JavaScript side, and then letting it just go crazy doing interesting things with it in the display.
So for the third step let’s talk about, in our application in particular, when the user clicked on that little iTunes icon that we had there, what happened? How did we make that pop iTunes without having to pull up Safari first and do that magical redirect that it does? Well what happened was, they clicked, it went through the bridge to this iTunes object, a little green cone that we’ve got it here in the picture, and we bridged a method in there that basically was the one that we used to open the album.
And so I’m going to show you the pieces of code involved in making that possible. Now there are other ways of accomplishing this particular task. We might have done one of the other APIs in the WebView, for example, intercepting a regular link click on a, on a anchor tag. And noticed on our own [inaudible] linked iTunes instead of letting it do the default settings, I’ll intercept that and then call iTunes. But we wanted to do it this way just to have a simple example of, of a bridged class.
So step one will be to write that custom object, the iTunes object in our case. Register it with the WebView. So every time the WebView is kind of cleared out, once it start off and if you have several refreshed, any of these bindings that we might create in it are dropped, and so we need to reinsert that. And then finally, call it from the JavaScript side.
So let’s look at each of these in turn. So the first one is writing a bridgeable class. And just like you might expect from the data example I showed it looks like any other Objective-C Class. Right? It’s got a view album method in this case, passing in albumID. On the implementation side here’s a simple thing to do, we happen to know the format of iTunes Music Store URL, so we can construct one of those using that albumID.
And then just call NSWorkSpace openURL. And that’s something that you couldn’t have done from any old web application running in a web browser. And it’s not a particularly complicated thing, but it’s a simple example for our purposes today. Just like we had to do on the data object for AlbumInfo, we need to make sure that the methods we intend to be called are accessible across the bridge. Remember, for security reasons it’s default deny. If you don’t do this part, JavaScript will not be able to call that method.
In this case we’re call, implementing is selector excluded from WebScript. So the selector will be passed in. We do a quick comparison to see if the selector is our viewAlbum: selector, passing in the argument. And if it is, we return no, do not exclude it. And again, in the default case we return yes to exclude anything else from being bridgeable.
Now we actually did one other thing here, this is small, but can be nice especially if you’re doing a lot of this. This can be nice for your JavaScript developer. We did, we implemented WebScript name for selector, which is another one of the methods in that informal protocol we talked about. And all this one is doing is kind of overriding the default naming strategies that the bridge has.
Especially any colon in your selector name for the method that being bridged will be replaced by an underscore in the name if it’s visible to JavaScript. And so this would have been viewAlbum_ if we hadn’t done this. And we decided to make it, look more familiar to our JavaScript developers, so we just told the bridge just use viewAlbum for the name for this on the JavaScript side.
[ silence ]
With that the next step is to expose that object to the JavaScript bridge. And as I said before, the, the WebView that we have, it gets kind of reset once when it, when an application first starts up, and that’s our chance to insert this binding of a name for this object, we’ve got this iTunes object. And it could also happen on a refresh.
And so, we implement the WebView did clear windowObject for a method. And that’s just a delegate method inside the WebView. So we’ve implemented this in our app controller, which is set up as the delegate. And all we’re doing here is just saying to the WebView, set value for key.
And the value is our custom object that we want to bridge, and the key, in this case iTunes, is the name we want that to have within the JavaScript so they can access it. And let’s look at what that looks like on the JavaScript side. On the JavaScript side it looks kind of like you’d expect if you were JavaScript developer. Window., the name we registered it under, in this case iTunes.method that we bridged. Passing in an argument. And that’s really all there is to it.
On the JavaScript side it looks just like any other JavaScript. So in summary, we’re exposing Objective-C data over the bridge to JavaScript. And in order to do that we want to be able to do things like pass it in as arguments. And again, one of the main theme here is, that informal protocol, the WebScripting informal protocol is your friend. That’s the thing that you need to be able to make anything accessible, because by default nothing is. We want to be able to expose top level objects to JavaScript, and we saw that just a moment ago. Registering with a WebView in the delegate method that we saw.
And again, just calling it from the JavaScript side. And really the main point of all this, it wasn’t a lot of code; it was a small amount of code that I showed. Most of the code in this application was a little bit interacting with the web services on the Cocoa side, and on the JavaScript side, display interesting things.
Right? There’s dot code, and the rest of it is small extra work in Objective-C allowed us to have native looking code in JavaScript. It looked like just any other JavaScript. And with that I’m going to bring up Ryan Orr, Engineering Manager in our front end group, to take you through more of the details around some of the things that you can do inside the WebView. Thank you.
[Ryan Orr]
So Gregor talked to you guys about creating the Cocoa application with a WebView, and then building a JavaScript bridge to pass the data from the WebView into the Cocoa layer, and from the Cocoa layer back into the WebView. But I’m here to talk to you guys about the other side of the thing, the WebViews, or the WebKit side of things.
And more specifically, some of the advantages of WebKit. So let’s take a, take a look at the first advantage of WebKit. And that’s the ability to leverage a diverse community of web developers that have a unique set of skills, so that they can easily create UI refinements and features for your application. Another advantage of WebKit is the ability to leverage CSS animations and transitions. Now this is the technology that was pioneered by Apple and proposed for inclusion in the W3C CSS 3 standard.
It allows you to quickly add Core Animation like Motion into your applications with just a little bit of CSS, so that you can add these very smooth animations and push them into your application. Another advantage of WebKit is the ability to leverage HTML5 Media Support. And this allows you to quickly add sound and media into your applications, and then using a bit of CSS and HTML you can add and style controls in your WebView. And then with a bit of JavaScript you can define how those controls interact with your media. And so this is very powerful, it’s a very powerful way to actually add this media into the WebView.
So remember this, this is a screen shot of the, the demo application that Gregor showed you guys earlier. And when we were taking a look at this we, we were trying to figure out, you know, what on this, in this application is actually going to be, you know, WebView. And so initially we looked at kind of the, the Tweet content here. Cause this stuff is, you know, this is prime for, for a, a, a WebView. You know WebKit can [inaudible] real easily; we needed to fluidly wrap and [inaudible] links in that content.
And WebKit’s very good at, at rendering this stuff. Like if you were kind of look at this content, you might as well expand it out an include the, the Twitter profile pick as well, cause HTML is a great way to actually lay out user interfaces. But if you have, you know, 50 Tweets on the screen, you need 50 WebViews, and that just doesn’t seem like a smart thing to do.
So you kind of expand that out, and you’d say, well why don’t we include that, this whole pane here, and you know, build that as a WebView. That makes a lot of sense. But, you know, if we’re going to, if we’re going to do this much of the UI as a WebView, why wouldn’t we just do the entire thing, right?
With, with all these advance CSS and HTML elements that WebKit can now support, we don’t really need to be limited by what the, what WebKit can actually render. And so we can do all this navigation. We can do all the animation, the switch between the different actions. And so that’s what we did.
This entire user interface was done as a WebView, and so none of it was actually built in Interface Builder. So what I want to do is I want to do a quick demo for you guys. I want to go back to this, this Twitter application that we built.
And I want, I want to use some of the advanced HTML and CSS properties to rapidly add a feature. And we’ll push that feature out to our application, and show that we can actually add these features without having to recompile and push the software updates to the, to the physical client on the desktop.
And just to refresh your guy’s memory here, here’s the Twitter client that we built. I have to resize this here. All right. Good. So one of the things that, that Gregor mentioned is that, you know, a lot of times people will send out like music links, right, that people want to check out. And you know, you click on them and it’s kind of a, it’s kind of a bad user experience.
You click on it, and it pops open Safari window, and the Safari window redirects into iTunes, and then you, you finally see the, the content that you’re actually, you wanted to see upfront. And that’s kind of a negative user experience. So we thought well, why don’t we just intercept that? We’ll make a call out to the iTunes API, grab that information, and we can denote it with an icon.
And so, you know, it looks a little bit like this. Boom, and it pops you straight into, into iTunes, which is, which is great. Right? We have the, the album artwork here; we have the album title, all the songs. If you double click [inaudible] you get a 30 second preview.
but you look at this content, this is all content that WebKit can display natively and it does a really good job of integrating it into any application. So why don’t we take this information, we’re already getting it from the, from the iTunes API. Why don’t we actually go and insert it into our applications, so that we don’t need to jump out of iTunes to view it.
So I’m going to close iTunes here. Let’s open my web files in the text editor. And before hand we, we, we had created a bit of UI to do like a little tray that we can pop down and prewritten some JavaScript. And so for the sake of brevity I’m just going to comment a line, comment out of line here. But essentially what the JavaScript does is it adds a class to the element.
And that class triggers the CSS rule that will pop down a, a drop down. Going to switch this real quick. Save this. And you can imagine at this point you would, you would upload these, these files to your remote server. We our, our, our file, our web server’s local, so. Here we go. We unload the Tweets here.
And so now when you click on this you get this nice drop down that pops down. It’s got all of our information that Gregor was already passing to us, and we were able to inject it into our WebView and style it the, the way that, that we saw fit. And so we still have the, the album art, we have, you know, the album title and all these songs.
And you see right here we have this display button that’s very reminiscent of the, the play button on the iTunes iPhone client. And what that is, is it’s actually an HTML5 media control that allows us to stream this 30-second preview that we got from the iTunes API. And so now if we, if we click this, we should stream a 30 preview.
[ music ]
And as easy as that you’re able to very quickly add all these different media types straight into your WebView without having to pop into iTunes. And we think that this adds a nice user experience for your customers. But there’s one thing that I don’t really like about this, and that’s when you click this it just kind of snaps open, right? We defined a height on the tray of 180 pixels, and we’ve flipped that class it kind of snaps down, snaps up.
Previously I mentioned CSS transitions, and this is a great way to kind of add the animation, like really nice smooth animations to your, to your application. So let’s go back in and let’s modify the CSS and add one of these transitions into the CSS and, and add a bit of refinement to the 2I.
[phonetic] Open my web files again. Let’s go into the CSS and we’ll [inaudible] the sign. Now this is a, this is a CSS property called WebKit Transition. And there’s a, there’s a couple of these, these CSS properties. They’re, they’re fully documented on, on ADC, so you can read more about them.
But this one is a, is a shorthand for a WebKit Transition that allows you to pass in the CSS properties you want to animate over, a duration, and then an animation algorithm. In this case for the close we’re using ease in, and for the open using ease out. So we’ll save that.
Let’s load our Tweets here. And now when we click on this we should get a nice smooth animation. And again when you click it, it goes up. And so this is a really, really quick way to add a bit of UI refinement into your application, quickly get it out to your customers without them having to take a software download, which is we think is a really, really great way to add value into your application. Anyway with that I’d like to hand it back over to Michael for some closing remarks.
Michael: All right. Thank you Ryan. So obviously we had some fun with that application. We’d like to than Warren Brictor, [phonetic] ADA Award Winner for letting us, giving us permission to rip on his application. We picked that application for a very specific reason, there’s lots of great Twitter clients out there, but what we liked about Tweety was that it was a very rich Cocoa experience. It’s a great interaction experience. If you haven’t used it, it’s just very beautiful and it’s really, it’s a, it’s wonderful to use. But what we wanted to do, and the challenge that we set for ourselves was, could we pull that off?
You know, could we pull off that user interface completely inside of WebKit. And as you saw we, we did a pretty good job, and we also added other functionality as well. So, but the point was, we wanted to get you to thinking about was, just don’t expect less out of the WebKit view. We obviously did a lot of, we did all of the user interface inside of WebKit.
And if you were doing a hybrid app, you’d probably pick and choose different parts of, of Cocoa and web inside of there to build your application. But we wanted to kind of push that. But I wanted, I wanted, we wanted you to think about this idea of match ups.
The idea of using the best benefits of different technology platforms to build things. It’s, we obviously we’re doing web and we’re doing Cocoa here, but there’s a lot of services out there that you can be using as well. It’s a nerd crime to real, not release, to release a web service out there and not have an API out there for users to actually get to their data and to share it with their friends.
We think this is a lot of, this is a ripe area for ideas around innovating new ideas. The other thing, and this is the reason the broadband guys came to us in the first place, is, Tony was talking about this, was one of the things we do well in this store is we take your money.
We, and anyone who’s built an application before gets to that part where you’re sitting there and you start to figure out, oh, I need to sell this. And that means there’s credit cards, and there’s banks, and there’s big words like SAP. This is a really complex set of things, and we’re not even talking about a, a worldwide solution here yet. Commerce we think is really a, a ripe area for innovation here, and embedding the experience inside of the application, we think, is something that’s going to be great with sort of a hybrid idea.
And like we did with the GarageBand experience, we think it’s a wonderful user experience to never leave the application to do something to buy new, to buy new content. So again, we think this is somewhat of it’s a lot of innovation. And lastly, you know we’re talk, you think about, we’d like to, we think about the browser as this thing, which is looking at server, files on a server, and as we talked about a lot today, it’s not just some, it’s not, it’s not something that is always looking at a server. It could be viewing content locally, help systems.
A browser is just a way to view a page, and you can also view pages as we talked about via the database, database APIs. I think that I kind of want to leave you guys with is, you know, this is, we’re talking about hybrid applications, but we’re just actually really talking about software development evolution.