Configure player

Close

WWDC Index does not host video files

If you have access to video files, you can configure a URL pattern to be used in a video player.

URL pattern

preview

Use any of these variables in your URL pattern, the pattern is stored in your browsers' local storage.

$id
ID of session: wwdc2001-114
$eventId
ID of event: wwdc2001
$eventContentId
ID of session without event part: 114
$eventShortId
Shortened ID of event: wwdc01
$year
Year of session: 2001
$extension
Extension of original filename: mov
$filenameAlmostEvery
Filename from "(Almost) Every..." gist: ...

WWDC01 • Session 114

Application Packaging and Document Binding

Mac OS • 58:17

This session covers changes to document binding and application packaging in Mac OS X and the impact of these changes on developers and users. Bundles, file name extensions, file type and creator, binding rules, the role of Launch Services, and Finder-related topics are discussed in-depth.

Speaker: Christopher Linn

Unlisted on Apple Developer site

Transcript

This transcript was generated using Whisper, it has known transcription errors. We are working on an improved version.

I want to welcome you to session 114, Application Packaging and Document Binding. And this morning, at the end of my session 111, I was talking about how, you know, some of the things that you need to do to create a great user experience on Mac OS X. And one of the things I mentioned was, you know, bundling your application. So we want to talk here in this session about how to package your application, how to bundle it, what the difference is between those two terms. We want to talk about document binding, what are the rules for Mac OS X and how documents are associated with applications.

And this is something you need to pay close attention to. It's something that's been discussed a lot online with some of the discussion lists. And we would like to clarify a little bit what needs to be done from the developer's point of view. So to talk to you through this material, I'd like to explain this material to you. I'd like to introduce Christopher Linn from the User Experience Engineering Team at Apple.

Good afternoon, almost evening. It'll be evening by the time we're done.

[Transcript missing]

And let me see if I can get this to work. Okay. So first half of my talk is all about packaging, how you deliver your applications on Mac OS X. And I'd like to talk a little bit about what the traditional delivery mechanism is or structure of an application.

And then look at this new choice, sometimes usually called a package, sometimes referred to as a bundle. I'll try to explain the difference between those two terms. And then really go into some amount of detail of how an application package is structured and look at some of the important internals such as the property list and how you express things like what types of documents your application can open and what types of URL schemes your application can handle. Then in the second half, I'd like to go into document binding in which we talk about what exactly does document binding mean, how does it work on Mac OS X, and how does it work on Mac OS X.

And therefore, what guidelines should you follow when saving new documents from your applications. Finally, I want to give a quick overview of what the capability of this new API is called Launch Services that essentially provides the binding service on X. And look at how you can make sure that your application, once it's installed, is actually also in the bindings database.

Okay. So let's start out with something simple. What is an application? Well, it's a database. Of course, it's a big hunk of code, a big program you've been working on, slaving over for several years probably, fine tuning it and adding features. But in order for it to work, there's a whole bunch of other stuff that needs to go along with it.

Localized strings, controls, and view layouts, icons and images, and help files, plug-ins, and I could go on and on. And all these things are really necessary for your program to run. So you want to make sure it all stays together. I call all this extra stuff the goo with your application. The goo needs to be there or else your application won't work.

The way that applications have been traditionally packaged has been with us since 1984. The original Mac OS introduced resource files, and in fact, everything was in the resource fork back then, the code and all of the extra goo. And it presented this great single-icon view of an application to your users. It was very clear to run an application, you double-click that icon. It had some other advantages in that non-programmers could get in with localization tools and create a localized version of your application. And this format is still fully supported for Carbon applications on Mac OS X.

But there are some limitations. Not everything can appropriately be placed in the resource fork or a resource file. And so as applications have gotten more complex over the years, You see that sometimes you look in a folder and you'll see a lot of other icons there. And some of this stuff might be necessary for your application to function properly. Some of the plug-ins, for instance. And in addition, it's just more complex for the user because the user has to find the right icon in order to double click and open your application correctly.

Another problem with this model is that when you localize a single file application, it only has a single localization in it. So you may have to make an English version of your app and then a French and a Japanese version and so on, a separate version with your binary duplicated for each one. And so it's just some extra work and more complexity for installs. And in addition, once the user installs your app, it can only run in that one localization.

So what we want to get back to is the simplicity that looks like this. One icon, it's an application, the user knows what to do, you double click it. And so what we're introducing is application packages. A package is simply a directory that to the user looks like a file.

What goes inside there is completely up to us. Apple defines a certain structure. You can extend that structure by or work with it. It's fairly flexible as to what goes inside there. And it can grow over time without impacting the user. The user will always see just this nice simple view. All the goo is hidden inside.

There's some other great benefits of application packages. You can have multiple binaries inside. So, for instance, you might want to set up your package so that it has one binary for Mac OS X, but it has a classic binary in it that can actually run when the package gets double-clicked on Mac OS 9, and we'll talk about that.

But I think the most exciting thing about application packages is how they can contain multiple localizations, as many as you want. And this means that you can have a single install of your application, and it works great on a multi-user system where one user logs in and prefers one language, double-clicks your application, that's the localization they get, the one they prefer. A different user comes in, speaks a different primary language, they double-click the same package, and they get the localization that they prefer, the language that they prefer.

Finally, although I'm not going to talk about it much today, packages are not just for applications. It's actually possible to define Document Packages, and that's something that Interface Builder uses. But mostly I'm going to be looking at application packages today. Interchangeably, you might hear me using the term bundle and package. And I'd like to try and clarify once and for all, maybe, what the difference is.

And the reason I use the terms interchangeably during this talk is that you can see right in the middle is an application package. It's both a bundle and a package. On the left, we have something that's just a bundle, and the example I have is a framework. A bundle is a directory that contains code and some associated resources, or GU.

But it's just a directory, okay? If it's just a plain bundle like a framework, you can actually click on it and look inside it. You see the contents. And the reason we didn't seal it up as a package is that there's actually some headers in there that we want you to be able to get at easily.

On the other side is something I call a Nib package. It's actually usually referred to as a Nib file, so you may not even realize it, but a Nib that is produced by Interface Builder is actually a package. And a package means one thing. It's a directory that is presented to the user as a file. So it looks like a file to the user. In the middle, again, you have applications. And as we go into the application structure, I'll try to point out what things about it are specific to bundles and what things about it are specific to packages.

So this is a quick overview of what the structure of a package is inside. At the top level, this is a sample application on the developer CD called Sketch. And basically inside, at the top level of the package, there's actually just one thing, another folder called Contents. So Apple chose to take all of its structure and put it in one place so that it doesn't conflict with anything you might want to do up at the top level. And really everything interesting about the structure is inside of the Contents folder.

The first thing is the property list. This is something that all bundles have, a property list. It's a file called Info.plist. And it tells the system, it's in a format that the system understands, and it tells us all about your bundle. And we're going to get into that in a fair amount of detail. So for right now, let me just go on.

Next is another directory called the Resources Directory. And this is where all of the goo goes, all of your resources, whether they're resource files or strings files or images, icons, anything goes in the Resources Directory. And there's two parts to it. Up at the top level of the resources directory, if you will, go all of your resource files that are global, that don't need to be localized.

And then for each localization that you want to add to your package, you have a subfolder which is named after the language for that localization. And the language names are defined by the Core Foundation bundle APIs. And so you can have as many of these as you want: English, French, Japanese, and so on.

And inside here is where you put resource files, localized strings, anything that needs to be localized goes down in here. And there's one file in particular I want to call out, and that is a file called Info.plist.strings. It turns out that some things in the property list up at the top level there, or in the contents folder, are actually user visible.

Things like the user visible name of your application and the kind strings associated with your document. Those things need to be localized. So there's a part of your property list that lives down in each localization folder, and that's in a file called Info.plist.strings. And a strings file, I'll show you a little bit later, but it's basically just a set of key value pairs that we can do a look up on to find an actual value for a string.

Okay, back up to the contents folder. The next thing is this PKJ info file. And if you look at it in the finder, you'll see it's always 4K. Well, in fact, that's the minimum block size. If you look at it in detail, it's only 8 bytes large. This is--the contents of it actually are not public, but if you look at it, it's obvious that it's the type and creator of your package.

Since directories don't actually have types and creators associated with them in the catalog info of the file system, this is where we cache it. And it's basically an optimization. You don't need to worry about this file except to know why it's there. Its presence helps us know that this is, in fact, a package and the contents may change in the future. as we deem necessary.

And finally, we get to where your executable lives. On Mac OS X, when an application package is launched, the system always looks in a directory called Mac OS with no space, even though marketing would rather it have a space. It's not actually user visible, so we just simplified it. And in here is where you put your binary. And in fact, the name of the binary can be anything you want. It never is user visible. However, in order for us to find it, it needs to be specified correctly in your property list.

So that is a simplified view of an application package structure. And I'd like to touch on one other topic related to the structure, and that is about packages on Mac OS 9. So I'm going to strip away all that other stuff about property lists and resource directories, because Mac OS 9 doesn't have any of that infrastructure. But we did want to give a minimal way for Mac OS 9 to recognize and launch packaged applications.

Obviously, it's not going to be able to launch the Mac OS X version, because you can't get it the resources down in the resources directory. But what you can do is create another directory to hold your classic binary. And this is actually a single file traditional Mac OS 9 application. It's going to have all of your resources in there localized to one particular localization. And the way you get Mac OS 9 to launch it is you create an alias. And actually, the alias can be called anything, because we just look for an alias, any kind of alias, inside the application package. And you make that alias resolve to your binary.

And the Mac OS 9 finder will be able to launch a package like this. So this is one way, if you really want to get on the package train and take advantage of all the advantages for X, you can still have a single package which can be run on Mac OS 9. And now I'd like to switch to the demo machine here and just show you a little bit about packages. So Sketch here is kind of the sample app I was going through. And it's a Cocoa application that does some simple drawing.

Close it and quit. And we kind of struggled with whether or not we wanted to do this in the finder, but it turns out that it's really handy to be able to have a backdoor to get into a package when you really want to inspect the contents. And so what we did was we put it down in the contextual menu.

So if you Control-click on a package, there's actually a command that says, "Show package contents." This is so you know it's there in case you need it. Here we have the inside of the package. It's a window that's actually rooted at the package. It doesn't go up to the rest of the hierarchy.

But it is a regular Finder window. You can change, say, to List View. And let's take a look inside. Here is the property list, the Mac OS directory with the binary in it, the package info file. And let's see. In Resources, we have a whole bunch of stuff actually. We've got TIFF files and icons. And then here we have some localizations, English, Japanese, and even Klingon there. It's one of the advantages of Unicode.

Let's see, and then in here we have nib files that get localized, and here of course is the Info.plist strings file which contains some of the localized information from the property list. So that is inside a package in the finder. And now let's switch back to the slides and move on.

So with all this talk about packages, you might be wondering how the system actually knows the difference between a regular directory and a package. And there's actually three things that can turn a directory into a package, and that was kind of necessary for historical reasons, I guess, for some existing packages we had. The first one is that we actually defined an HFS catalog info bit that was unused for directories, and we call it the package bit. If you need to know, it's bit 13.

It corresponds actually to the bundle bit for files, but for directories it was unused. I'm told that in the original Mac OS, Planning back in 1984, they wanted to do something like this and it only took us, what, 16 years? 17 years? So there's a bit, and when you set that bit, magically the directory gets presented as a package. Now that's actually not quite enough information because since directories don't have types and creators, we don't really know anything about that. So it's always good to have a package info file there.

Whether or not you use the package of it. But it turns out if your directory has some sort of valid extension and a package info file in the contents folder, that's enough to tell us that it's actually a package. And one other way is, and this is documents as packages, if the directory has an extension on it and that extension is claimed by some application as a packaged document, then we'll know from our bindings database that this directory needs to be presented as a package. But typically, application packages, you want to have the package info file so that we know that it's an application.

So the rest of the time on packages, I want to talk about the property list because this is really how you communicate to your application what your application-- or to the system what your application can do. The property list tells us things like what the name of your executable is so we can launch you, what version it is, what types of documents you can open.

And something we've added is what kind of URL schemes you can handle. So if you are an FTP client, you can handle FTP URLs or a browser or even if you have your own private schemes. You can specify them here and that allows the system to route a URL with your scheme to your application.

Again, the property list is something that all bundles have. It's-- in fact, the Core Foundation Bundle API is what you use to manipulate bundles. And all of the keys that I'm going to go over soon, I'm going to go over in a minute. start with CFBundle because this is all defined by core foundation.

In general, the property list has a lot of parallels with the single file application model. Reverse resource, BNDLs, FRF, open resources and kind resources. All this information is now in the property list, as well as additional things that we're adding over time. The property list itself is actually just a text file. It's an XML file, which means that Core Foundation can easily read it in as a property list.

It's implemented as a dictionary, which means it's easy to extend. We just add new keys, and when you ask for a value of a key, Core Foundation dereferences or looks up the key and gives you back the value. We've defined a number of standard keys, and these are the things that the system looks for when scanning over your application package.

As I said before, some of the values should be localized. I'm going to keep saying this because I just want to keep reminding you. If you don't localize, say, your kind strings in the right place, then they won't be ready in the finder for users to see your kind strings.

Now, what if you're actually not quite ready for packages, but you really want to have a property list? And this is important because, in fact, if you really want to get nice, big, Aqua icons associated with your documents, you need a property list. Or if you really want to make sure that you're able to claim certain extensions, file extensions, then you need a property list. So we've made it possible for single file applications to also have a property list.

In fact, if you do this, then it's one way we know that you are actually a native application and not a classic application. What you do is you create a PL/ST resource with ID 0, add it to your application, and simply paste the contents of your XML property list into the resource.

The only thing that has to change is that in the places where you're specifying an icon, instead of specifying a file name for the icon, you actually are specifying a resource ID. So it's just a number. Then we look for an ICNS resource with that ID in your application. Okay. Now, let's keep moving here.

These are not all of the keys that you might see in a property list, but these are the essential ones, and I wanted to zip through each one. CFBundle Names. It's a name for your bundle. It ends up being a user visible name, so this is something that you want to make sure you localize in your strings file. Where it's visible right now is, say, in the menu bar. The application menu is actually that text comes out of your property list.

Something that's not user visible is the CFBundle identifier. It's designed to be a unique identifier, so we use the form of a, like a, in the style of a Java package name, kind of a reversed domain name. And this gives us a name, nice name spacing and allows the system to count on using this as a unique identifier for your application or bundle.

In addition to the package info file, we also want the type and creator to be in the property list, so the package type for applications, it's always going to be APPL. And then of course the signature is the same as the creator, and that's your four-character OS type that still should be registered with Apple so that we're assured of some level of uniqueness for creator types. or creator signatures, I should say. The version, this is important for helping the system differentiate between different versions of your application. That sometimes comes up in Launch Binding or Document Binding.

and the icon file, this tells us what icon to actually associate with your application package in the finder or in the file dialogs. And then finally the executable name, which is the file down in the Mac OS directory. Now there's two others that are a little more complicated, and so I'll have to drill down into these. The document types and the URL types. These are how you associate documents on the system and URL schemes with your application. It lets us know that your application can handle various types of documents and URLs.

And those keys are actually arrays, and each value in the array is a nested dictionary again, so it's all very extensible. So for each document type that you can handle, we have a number of keys. And I'm not going to go through the URL keys, because they're very complicated. They're very similar. And I want to really focus on document binding today.

The first one is an abstract name for the type. And this ends up being user visible. This is actually the kind string. So you want to make sure that this key gets localized in your strings file. Moving on, the icon file. This tells us what icon-- we go and look for this resource in your-- for this file in your resources directory and associate the icon in there with documents of this type in the finder.

The next one is a new concept, the role. We're introducing an understanding of roles in Mac OS X. And this is a way to give us a little more information about what your application can do with documents of this type. And the only two we have defined right now are editor and viewer.

So full-blown Acrobat is an editor of PDFs, but Acrobat Reader is a viewer of PDFs. And that's about as clear a definition as you're going to get of the difference between editor and viewer. It's not always so clear, but we think it's a pretty useful distinction in a lot of cases. This actually is a required key. You've got to tell us. You're one or the other. And it comes into play when we're doing document binding.

And then, for each abstract type, you can actually associate a number of OS types, that is type signatures, as well as extensions with a given abstract type. In the case of OS types, the reason you might want to have several instead of just one is suppose you rev your application and change the file format, so you want to change the OS type for your document. Well, those are really kind of the same abstract type for the most up-to-date version of your application, you can handle all of those types. You would list them here in the array.

And similarly with extensions, you might have extensions that have changed over time, or you might have different versions of really the same extensions, such as HTML and HTM. You want to treat those as really the same abstract file type. So you can list them all in this array of type extensions. And let's see, I guess I have a demo here. What do I need to do? Right, so here is the property list, and I was just going to open it up in BBEdit.

BBEdit does some nice coloring. So, as you can see, it's an XML file. Here are the tags, like here, this says that this particular XML file is a dictionary, like I said. And there's a number of keys, some of which I've talked about. All of the CFBundle types, there's an array of types, and each item is a dictionary, like I said. If we look down, here's some of the other keys I talked about. The executable name is Sketch. The icon is Sketch. The icon file is actually Draw To App.

And obviously, this is not the best user interface for dealing with property lists. And so, if I actually go out here and double-click this, it will open in a little tool, a developer tool called Property List Editor. It gives you a much nicer interface for creating property lists. You can see, you can progressively disclose the property list to see all the keys we've been talking about, see all the document types. This is an array. There's several types that are supported by Sketch. So, this is a nice tool for actually creating a property list.

But in addition to that, both Project Builder and Code Warrior provide assistance in building your property list. Down inside the resources directory, again, is where the Localized part of the property list is, and if you look in here, you can get by all the disclaimers. What's in the strings file is the same keys, for instance, the bundle name, and then the localized value of it is sketch in English. Okay, end of demo.

So that is not all the details about application packages, but the message we really want you to hear is that they're a new option that has great advantages over the single file application structure. It gives a nice, simple, Presentation to the user with a lot going on inside. Because it contains multiple localizations, your application is actually globalized.

You take a single image of your application and it can run in many different languages. Not all at the same time, but it changes as needed. And because of the way the definition of a package is set up in a bundle, it's very extensible for the future. The key to getting a great user experience for your application package on X is getting your property list right.

And the best way to do that is go out and read the documentation we have. There's various tech notes on this subject. And also look at the sample code. The sample apps try to do a good job of having their property lists just the way we want them to be.

And that brings us to the second half, Document Binding. So, it's great. The system knows all about your application now. If you have a property list, we look at that. If you have a P-list resource, we look at that. Or if you're a single file application and you have a BNDL and F-Ref resources and Kind resources, we still look at that. And we have all this information about what your application can do.

Document binding is What makes this work? It's the service that associates on the fly documents in the file system with the applications that can handle them. It's what makes double click work in the finder. And as a general term, I'm using it to refer to the new capability of binding URL schemes to applications as well. So, In order to understand what's changing, I want to look at how things used to be.

In 1984, The Mac was introduced and we had totally free-form file names and we introduced type and creator in order to free the user from having to worry about Metadata and how documents get associated with applications. And that worked great because there wasn't a whole lot of file exchange going on. Every Macintosh was kind of an island and the file exchange that was happening tended to be between Macs.

If we fast forward to today, The picture is a lot more complicated. The world is a lot more interconnected and it's not so simple anymore. So for instance, we've got files that come onto the system, say from outside sources, through an email program, for instance, and all we know about the file maybe is its file name and its bits.

So... In that case, we can look at the file name and say, "Hmm, well, it has an extension, and that doesn't do us much good on the Mac." So the email client is the gatekeeper, and it's responsible for figuring out what is that extension mapped to. Because if that email program doesn't set the extension, or I'm sorry, doesn't set the type and creator, then it's not going to be very much use to a Mac user. And so the gatekeeper takes care of that transition.

Similarly, files going out, if Letter to Mom doesn't have an extension on it, it might be going to a Windows user. And the file's not going to be much help to a Windows user who doesn't know how to open it, because it doesn't have an extension on it. So the gatekeeper, again, is responsible for doing the transition. It might say, "Are you sure you want to do this? Do you want to add an extension to this file?" In fact, that happens sometimes, but not very reliably.

Another problem with the gatekeeper theory is that you can't always tell when you're crossing the boundary. Maybe you're putting a file onto a disk. It might be a file server or a removable disk. It looks like an HFS disk. Maybe it's an AFP server. You don't want to force extensions in all cases there. But the fact is if the file doesn't have an extension and the disk is accessed by a Windows user or another operating system, it probably isn't going to need an extension in order to be understood. But you can't tell that it's actually gone through a gateway.

And just to add one more thing to the mix, Macintosh is working as web servers or hosting a lot of files that have extensions on them. And so right on the system you've got files with extensions on them, and yet the system still knows very little about extensions.

So the gatekeeper theory kind of breaks down in this very interconnected world, and we're left with a lot of file exchange going on and not always a good user experience because document binding doesn't always work. So what's the answer? Well, if this was an episode of Star Trek: Voyager, I would say we could just assimilate Microsoft.

and we could banish extensions from the universe and make sure that everyone was using types and creators. I don't know what the Linux people would have to say about that. That would be nice, huh? The problem is we're the good guys, right? That violates the prime directive. We can't do that.

So the next thing that happens, whenever you're doing battle against the Borg anyway, is you remodulate your shields. There's two problems with that. First of all, it never works for very long. The boards see right through that, right? The other problem is, it has nothing at all to do with document binding. So we can't do that.

However, it occurred to me that what we are doing is something that Captain Janeway does all the time. She takes an alien technology and uses it to her advantage. And that's what we're doing by recognizing extensions on Mac OS X. Extensions are out there. They're on Mac systems. They're coming in all the time.

And the fact that we don't recognize them at all is just getting in users' way, in the way of users. And so I picked this word "recognize" very carefully because... We're not trying to get rid of anything else. We're just saying that extensions are an interesting piece of metadata. It tells us something about a file. And we want to provide the best possible user experience for our users. A lot of users are interacting with extensions by necessity. And the way to help them is to recognize them as a part of the system.

So what comes from that decision? The goal of document binding remains, and always will remain, that we want to always launch the right application when opening a document. The right application, of course, is what the user wants. So we have to do some mind reading. If we could read the user's mind, that would be great. Document binding would just work.

Our goal is to approximate mind reading as much as possible. And in order to do that, we want to recognize all available type information. Type, creator, extension, whatever might become available in the future. In addition, we want to give the user a little bit more control, actually, of how binding works so that they don't just have one choice for binding, that they can do some overriding if they want.

Now, the user experience we have in Mac OS X is not completely done. Extensions are fairly new to the system and... We're on our way to something that we think is a great user experience and I'm just mentioning this because I don't want you to think that what we have in Mac OS X we think is perfect. It's not perfect. But we do think it's an improvement, especially for users that need to work with extensions a lot.

So first of all, what is an extension? Well, we've tried to give a fairly constrained definition for an extension because we're adding it onto a system that already has a bunch of files on it. Some of those files might have extensions. Other files might have things that look like extensions, but are just, were just put there by the user and aren't really extensions. Something like, well, I don't know, but by constraining the definition of an extension, we are reducing the number of false positives on finding an extension. So, the extension is all the characters following the last dot.

The character set is A through Z, 0 to 9, dollar sign, percent, underscore, and tilde. Notice there's no spaces allowed in extensions. And there's one more restriction. If, although digits are allowed, numerics are allowed, if the extension is all numbers, then it's not seen as a valid extension, so it's ignored as an extension by the system. So, what are some examples of this? Well, first two.

There are similar document names. They both have a surfpaint extension, but with slightly different capitalization. Those are actually recognized as the same extension. Extensions are always matched case and sensitive. So those are the exact same extension. Listview.c, of course. And the last one, an mp3 file that has a digit in it, but it also has letters, so it's a valid extension. The invalid ones, surfpaint1.0.

That's just an extension. So, it's not a valid extension. Surfpaint1.0.v2 has a space in it. We disqualify that. And if somebody likes to put dates at the end of their file name, and it ends in .01, that's not a valid extension either. So, those things are right out. We don't recognize that as extension metadata. Okay.

So given all of that, how do we actually bind documents in Mac OS X? The first thing is that users can, for specific documents, : So, in the info window of the finder, there's actually a panel that allows the user to say, "For this one document, I always want to open it in this application over here." And that is the first rule in the overriding rule that if the user has set that, that's the application they're going to get. Now, if that's not set, which would generally be the exception, because that's an advanced feature, not something where obviously we don't want to require users to do that, the next thing we look at is the creator.

We look at the creator and we say, do we have an application with this creator on the system? And if we have more than one, we have to do some best matching, which I'll get into. But the important thing is, if the creator's there and we can match it, then that's how we're going to bind the document. I want to point out, this is how it works on Mac OS 9. This covers 99% of what happens on Mac OS 9. So right here, you're getting behavior that is pretty much in line with what happens on Mac OS 9.

The next thing we're going to look at is the extension, if there is one. If there's an extension, we want to consider it first because there's some important cases when the extension actually has more meaning in it than the OS type. And a great example is text files. They're all T-E-X-T on the Mac, and that's why you see text files with extensions on them, so that the system can tell the difference.

Now actually, the Mac OS 9 system can't tell the difference very well, but on 10, we can look and say, "Oh, it's an HTML file. It doesn't have a creator or the creator's missing, but we're going to launch it in Internet Explorer." Or, "It's a .c file. We're going to launch it in Code Warrior." And then we look at the OS type.

If we don't find an extension match or there is no extension, then we look at the type and we try to find an application that can open that type of document. In all these cases, there might be some ties. So let's look at how we break ties. For creator binding, well, Let's say we find more than one app with the same creator.

In general, it's going to be a different version of the same app. And we break ties in that case by always launching a native app over a classic app. If there are two native apps, for example, then we'll look at the version numbers in the bundle or the verse resource. And then finally, if that fails, then we'll try to break the tie by the latest modification date. And if that fails, then we'll try to break the tie by the latest modification date. have the same app and it doesn't really matter.

If we have to drop down to looking at the type in order to achieve the binding, then we look again at a user preference. This is an advanced feature, so most users won't be doing this, but it hits the spot when you need it. And that is, you can say, the user can say that HTML files, I always want to open them in Explorer. For any particular type, the user can specify their preference.

If that's not set, then we have some other rules, and this is where the roles come in. If we have an editor and a viewer to choose from, then we'll pick the editor. And by the way, unless classic apps indicate otherwise through a property list, all classic apps are viewers, considered viewers. And so this will also give an edge to native apps. But finally, if all things are equal, then we'll still pick a native app over a classic app.

So that is, in a nutshell, the binding rules. There are some nooks and crannies that I didn't get into, but that's the essential expression of what happens. So, given all of this, what are the guidelines for creating new documents on Mac OS X? Well, You want to maintain binding for everybody, ideally.

And so this actually came up on the discussion list recently, AppleHIDEV, and a pretty good way to put it is, save all the metadata that you have. So if you're an editor for a type of document, and the user is saving that document, it totally makes sense. You're the creator for that document.

You should set the type and creator for the file, and if your users might possibly be interested in opening that file on another OS, then the best policy is to also have an extension for that document. You might not want to force that, but a number of large applications already do, and not just Microsoft applications, I might add. It's something that our users need in some cases.

And so having all the metadata there, It enables us to do the best possible binding and for binding to work on all operating systems. However, there are cases when you're actually manufacturing or deriving metadata. And that might not actually make sense to save metadata that you have to derive. So for instance, if a file is incoming over the network as an attachment, You might just have an extension.

And you can ask Internet Config for, you know, you can do the gatekeeper thing and say, what's the type and creator for this? Well, the fact is, what you're doing when you ask that question is Internet Config is consulting the Launch Binding, or the Document Bindings database, and it's giving you back the same information, essentially, that you get when the document is double-clicked in the finder with just an extension.

So by, in other words, by saving the type and creator at that moment, you're kind of freezing the binding for that file at that moment, when in fact all of that happens dynamically now in the finder. If there is just an extension, your file will bind just fine. So there's no need to derive new metadata.

Other interesting things that you should do when you create a new file. Users like to see their files show up immediately. They like to see it in the finder. They know that their data is all nice and safe on disk. And the Finder does not pull periodically. That's a big performance problem if you do that.

And so on the chance that your file is visible in the Finder, or should be visible in the Finder, after you save a new file, or after you remove a file, for that matter, if you do, you can call this new function on Mac OS X, fnnotify, passing in an fsref to the directory that the file is in.

And that will wake up the Finder, and maybe some other clients for the notifications, and the Finder will redraw its window and the file will appear and the user will see it, even with the window in the background. By the way, the save panels in both Carbon and Cocoa will do this for you. So you don't have to do it if you've gone through a save panel to create a new file. Wildcard document types.

Well, Used to be in a single file application you could claim four stars and get wildcard binding for drag and drop purposes. And you can still do that in your property list. If you claim four stars, you're saying that you can open any file at all. Any file can be dropped on your application. We've added one new one which is claiming an extension of star, just one star.

And what that does is it's a little bit different. It says you can open any file that has an extension. And that's somewhat useful because you're saying that you open any file that has an extension and that you're going to look at that extension to figure out what the file is. That's why it needs to have one. Both of those can appear in your property list.

And finally, the last thing I really want to go through in this talk is how to open a document and the Launch Services API in general. This is a new API available only on Mac OS X. It is the engine that does document binding. It opens documents, it opens URLs, and it also provides some API for getting all sorts of information. So if you have a file or a folder or an application you have some questions about, then, Use Launch Services to get that information. And let me go through real quick how it works. As I said, it's only available on Mac OS X.

It maintains the bindings database. It does also save relevant information back to the desktop database, so that if your user does boot back into 9. Anything that got installed while 10 was running is in the desktop database to the fidelity that the desktop database can handle. And finally, oh, however, I should say, don't rely on the desktop database for getting binding to work on X.

In fact, there is one more step in document binding, which is a last-ditch effort to bind things. If all else fails, we will go back and consult the desktop database to see if we can find some application to open a document. But it's really the last resort. And if you want to work well on Mac OS X, you want to make sure that your application goes into the Launch Services bindings database.

Launch Services is used extensively by the Finder. It's essentially code that used to be in the Finder that did all the bindings. What we've done is we've made an API public so that you too can be like the Finder. If you need to open things, you want things to open in the same exact application that would happen if the user double-clicked something in the Finder, use Launch Services.

So what can you do with it? Well, you can open documents and URLs. There's two ways. The easy way, which is, takes an FSRF or a URL, and what that does is, the easy way is essentially the same as double-clicking. There's no options. You just say, take this thing and do the right thing with it.

And it's the same as what the user is asking for when an item gets double-clicked. If it's a URL, we look at the scheme, we find out what the best application is to open that particular kind of URL, we launch the application, and send it the URL Apple event.

If you need more control than that, then there's API available that allows you to do things such as launch more than one document at a time. I have an array of documents. I want to open them all. And by the way, I also want to open them in a specific application, not the default application, but I know the application I want, so I'm going to specify that. And there's some other options, such as passing Apple event parameters to the application when it gets launched, some pass-through params.

All of these things, by the way, are in LaunchServices.h on Mac OS X, and there's some extensive header documentation in there that will help you figure out exactly what each part of the API does. There's also a tech note on this, which we'll give a URL to at the end.

The rest of the Launch Services API is all informational. It allows you to answer questions that you have about various things. So, for instance, lscopy item info for ref or for URL. This allows you to pass in options, essentially asking questions, saying, is this item a package? Is it a volume? Is it an application? You know, I have an FSRef. I need to know something about it.

If it is an application, is it classic or a native app? Does it have an extension and what is the extension? Don't rely on just looking for the last dot in a file name. As I said, there are rules about what's a valid extension. Launch Services defines those rules by providing the API to get at the extension.

Getting bindings information. If you want to find out what the binding is for a document without actually opening it, or for a URL, you can call this Get Application for Item or for URL. And it will actually return to you an FSRef or a CFURL to the application that is the default binding for that item.

If you don't have an item but you have some metadata, a creator, a type, or an extension, or maybe all three or some combination, you can pass in whatever you have to get application for info and it will return to you the best possible, the best match for binding that metadata.

And finally, this is kind of an oddball, but if you have something else to identify an application, such as an application name or just a creator or a bundle identifier like com.apple.sketch, this API will go and find, search the bindings database for that application. And that might be something, especially with bundle identifier, might be something you need to do.

Drag and drop. Again, the Finder uses this in order to figure out drag and drop acceptance, so you can too. You've got two items. You want to know if one can be dropped on the other. You call lscanref accept item or can URL accept URL if you're dragging around a URL.

Kind strings. You need to know the kind string for a document. This API returns for a document or even for a URL the kind string pulled out of the bound application. So it does the default binding and it goes and looks in the package, looks in the property list, and finds the localized kind string for the document, returns it to you as a CFString.

[Transcript missing]

All right, how do you make sure that you're in the bindings database? It's kind of embarrassing if you install your application and then your user can't get it to launch by double-clicking a document. Well, Today, the Finder is solely responsible for updating the Bindings database.

And it does some things automatically for you. Whenever the user logs in, The Finder looks in some well-known places, such as the main applications folder for the system, the users application folder if there is one, some other places I think like scripting additions. And it notices if anything has been added or removed in those places. And it scans the subfolders as well, not just the flat folders. And it makes sure that all the applications in those locations are in the bindings database.

Whenever an application is launched by the user, say, right in the finder, you double-click on an application or you double-click on one of its documents. The Finder will make sure that that application is in the bindings database. Obviously, if you double-click on one of the documents, it must already be in there. But if you launch the application, it will get added to the bindings database. But you also need a way to install your application and make sure it gets added to the database. And the way you do that today is you need to tell the finder about it.

And the way you do that is with an existing Apple event protocol called the Sync Apple Event, or KAE Sync. This constant, I think it's in finder-registry.h. And what you do is you create one of these sync Apple events. You make an alias to your application, not to the directory it's in, but the application itself, the package or the binary.

You add that alias to the sync Apple event and you send it off to the finder. And that wakes up the finder. The finder adds the application to the bindings database. So if you're installing, well, what are your choices? First thing you could do is just rely on packages for a nice drag and drop install experience. You have a CD, you put your application on it, the user pops in your CD, drags the application package over, all the goo is hidden inside the package.

They drag it over, they double click your document, sorry, double click your application and boom, it gets added to the bindings database. But certainly there are going to be cases when you need to do something a little more formal than that. So if you're installing multiple applications or something, run through your installer, but don't force a restart or a logout.

You might want to make the user log out, they'll log back in, the finder will scan and find your application. But there's a much nicer way to do it and that is with the sync event. So copy over the application, send the sync event, everything goes into the bindings database. If you have more than one application, obviously send one event for each application.

So in summary, for document binding, our goal remains, and always will remain, To read the user's mind, to make document binding work intuitively. In order to achieve that, we've added a new type of metadata to our bindings information that we consider the extension so that all available type information is recognized by the system. And this should result in ultimately a better binding experience for the user.

We've also added the ability for the user to exert some control for advanced users over specific binding of specific documents. And in general, the best practice for you in creating new documents when you're the editor of the application, when you are an editor application, is save all the metadata you have.

Type in creator. If your user wants to work with extensions, save an extension also. That will ensure that your document can be correctly bound everywhere. And finally, the Launch Services API is really your access to all of this. It gives you all sorts of information about bindings, and it's exactly what the Finder does. And so it's a great way to mimic the Finder.

So there's some relevant sessions here. Localization is on Thursday. Designing icons is on Friday. Core Foundation and the bundle APIs for accessing bundle contents on Friday. A couple of project builder sessions, unfortunately, were yesterday and today. And finally, if you want to learn more about shield remodulation, be sure to catch Star Trek: Voyager's final episode right here tonight at 8:30.