iPhone • 1:03:46
Learn to customize Xcode features such as code completion, the code editor, and key bindings to suit your taste. Discover new Xcode shortcuts to documentation, sample code, build-results views, and build settings. Find other useful ways to enhance your coding sessions, whether you are a new or experienced Xcode user.
Speakers: Andrew Pontious, Dave Ewing, Justin Gareau
Unlisted on Apple Developer site
Downloads from Apple
Transcript
This transcript has potential transcription errors. We are working on an improved version.
Welcome to Customizing Xcode for Your Development Work Flow. My name is Andrew Pontious. I'm a manager on the Execute IDE Team. So what are our goals for today's session? We're going to demonstrate how to tune Xcode's preferences and setup to your liking. We're going to show where you can find the features and capabilities of Xcode that aren't necessarily turned on by default and how to change them to suit your needs, and with the end result being to allow you to work faster and more efficiently in Xcode to get the job done. So let's talk specifics.
We're going to start talking about the text editor. Now all of you use Xcode's text editor every day. But there are some things that we're going to show you today that you probably haven't seen already. Then we're going to show you how to customize and configure Xcode's build system and show you some of the options you have when debugging your application. And finally we're going to show you how to make the most of Xcode's source control management integration and Xcode's snapshots feature. So let's get started with text editing and for that I am going to bring up Dave Ewing. Dave.
[ Applause ]
Thanks Andrew. So I'm Dave Ewing an engineer on the Xcode team. So I'm going to talk about 2 broad areas with the text editor. I'll talk about using some of Xcode's built-in features and how to use them together more efficiently and I'll talk a bit about extending the features of the text editor, text editor. So the editor itself has many features. There's the code completion set of features.
We'll go into a bit about how they work together. There's text macros which is perhaps the most underutilized feature in the text editor. I'll show you how to I won't show you how to set up key bindings but I'll talk about it a little bit, but to to get the most out of these different features. We'll talk about some new features in the recent releases of Xcode with regards to navigation and the new feature in Snow Leopard, Quick Help. So we've made quite a few improvements to Snow Leopard to code completion in Snow Leopard.
There is a few subtle changes to the user interface mostly with regards to keyboard handling. I'll get into that a little bit more when I show you in a demo. But most of the changes for code completion are under hood under the hood. We've made it much more aware about the context in which you're editing so that the completion list that it comes up with is much more accurate, much more appropriate for that context.
And of course there's performance. We're always working on performance with code completion. We've made some specific improvements in Snow Leopard that work really well for when you're editing in large files. Finally there's perhaps the longest requested feature in the text editor that we added in Snow Leopard the ability to automatically insert a missing open square bracket when you type the closing square bracket.
[ Applause ]
OK a little more about code completion. There are 3 modes, modes of operation with code completion. There's the in-line code completion where as you type it will show you the best completion it comes up with right there in the text. That's how Xcode comes configured out of the box so that's how most people use it of course. But there's 2 other ways you can get access to code completion. There's the next completion command which is in the edit menu. You can bring it up with control. that cycles through the handful of most likely suggestions.
So when in-line code completion isn't suggesting the thing that you want it's very likely that it's still in the top handful of suggestions so you can use the next completion command to cycle until you get to that suggestion that you're looking for. Then there's the pop-up list. So you can hit the Escape key and bring up the completion list. That's really useful when you're not sure what API you're looking for.
So that's a quick way to look at the possible completions. But there's 1 other way you can use code completion and we call it the in-line pop-up list. So what that is is as you're typing rather than inserting the text to show you the most likely completion it can pop-up the list for you as you type. Now that's how code completion works and a lot of other IDE's so many people are more familiar with that when they're coming to the platform.
To get that you have to set a user default in the terminal. The user default is XE code sense auto suggestion style and you set it to list. So text macros: Text macros are little snippets of code that you can insert into the text editor. They can actually wrap around the current selection. They can do some variable substitution in them as well; it depends on the current context. You can insert them either via code completion or through the Edit menu.
Now inside the Edit menu they're down at the bottom; there's text macros and there's another layer of menu items and then all of the text macros and it's not really convenient while you're editing. So this is 1 place where you really want to attach your custom key bindings to your favorite text macros. Speaking of key bindings; you set those key bindings in the Xcode preferences panel. You can set key bindings for all the menu items in Xcode and all the text editing commands.
Now there is a lot of commands in there in the text editing section that don't have key bindings assigned to them. So if you're looking for a feature that you think Xcode should have it may be there and you just don't know about it or you don't know about the key bind, it may actually be bound to something.
One thing to note when you customize your key bindings, when you then go and upgrade to a new version of Xcode it has some new menu commands or new text commands that have key bindings assigned to them you won't get those new key bindings. So there are 2 ways you can fix that, both of which are pretty easy. You can go back to the Xcode default key bindings and reassign the custom ones that you had assigned before or you can take your custom key bindings and just add new key bindings for the new commands.
Navigation: So there's the open quickly command which actually went through a big face lift in Xcode 3.1. It's always been used where you type a file name and it takes you directly to that file but you should know that you can type any symbol that's in your project and it'll take you to that symbols definition within that project too.
New in Xcode 3.2 is the incremental Find banner. So this, in older versions of Xcode we brought up a separate window you could type things in and go back to the editor. Here we brought it nice in right close into your editor. As you type it highlights the matches as you go. Another new feature and perhaps maybe the other oldest bug that people have been wanting fixed for a long time, or enhanced is the history.
So traditionally the History buttons in Xcode have only included the files you had open. In Xcode 3.2 they include all the navigation you've done within the current file, well within all the files so...
[ Applause ]
And finally in Xcode 3.2 there's new Quick Help. So Quick Help is a floating window that gives you a nice API summary for whatever symbol you have selected in the editor.
You normally bring it up by option double-clicking on that symbol. But if you want to keep that window up you just drag it off to the side and it will stay there and it will continually update when you move around in your file. If you like you can customize what's shown in the window. Right here we have an example where it's showing all sorts of stuff. Links to sample code, links to related API and related documentation. But you can go into the Xcode preferences and trim that down if you want.
You can reorder how it shows those if you want to. In the top right corner of the window there's 2 buttons for you. One will take you directly to the documentation for that API and the full documentation viewer and the other one will take you to the declaration in a system header file. So with that, let's show some of this in action. OK we have a simple project here. This is the example we'll be using through this whole session is Zip browser which is available as a sample code from the ADC website.
I'm just going to open up one of the documents. So you can see at the top of the window there's the file navigator here, there's the window, the files that are open in this view, only 1 of them right now; the Function pop-up. You can bring those up with the keyboard too. Control 1 brings up the File menu. Control 2 brings up the Function pop-up and you can type to select and go to somewhere in the file. So now I'm going to show a little bit about code completion.
So let's go down just a little bit further here. Woooo. One of the easy ways to show off code completion is just sort of reproducing a complex statement above. So I'm going to reproduce this statement here. So let's go ahead and just start typing self. Now of course I forgot this open square brackets which I'm forgetting more and more these days actually because I can put them in. So that that works nicely. Let's go ahead and start typing.
You clapped once already. Don't clap again. So present error. It's suggesting one of the options for present error. Let's look at that in the completion list. There's 2; the full method that I actually want to insert here. Now if I hit the Tab key with the completion list up here new in 3.2 is we complete to the sub the sub common sub string for the items that are selected.
So I actually want to select the other one so we'll just go ahead and do that. So now we've got this message call here that we've got to fill in. We've got a bunch of code completion place holders here. Also new in 3.2 is you can tab between them.
There's a next...
[ Applause ]
The magic Tab key, man, my favorite key. So you can tab between them actually Shift Tab goes backwards through them too. So let's go ahead and fill that one in. So E it turns out there's loads and loads and loads of things that begin with E, you're probably not surprised by that right? But the next completion command is really handy here because E error is a local variable; it's by far the most likely thing to insert here. So we'll just go ahead and hit Control.
and insert error. So we'll go ahead and start typing a little bit more. Zip a Zip document browse document browse I'll just hit Tab to complete that window and of course missing square bracket we'll put that in and do a few more here. Nil zero and null and of course it corrects my capitalization, that's what code completion is for.
OK so those are the different 3 modes. Nothing really modal about it with code completion. Let's say we want to put this statement, let's write some new code just as interesting as the old code. Put this statement inside of an S statement. So you could go ahead and type that, that works fine but there's also a text macro for that and as I said it's down inside and let's even get through the hierarchal menus and I've assigned a key binding for it already. So I'm just going to use the key binding and it wraps whatever you have selected in the editor So we'll just fill fill that out. Whoops I hit Escape. OK so there's other things you can do with text macros.
Let's say we want to if def out a block of code. So I also assigned a key binding for that, you guys if you were looking might have noticed it and you can go ahead and wrap code. One of the cool things about text macros that are in menus though is that you can assign more than 1 of them to the same menu item so that they cycle through those and so if I keep hitting Command Control 3 cause that's my magic personal preference for this key binding. I can go and turn it into an F 0 block, an if def block, an if block with some L's and back around to the beginning.
So, so there's some text macros. OK the next thing I want to do is show the incremental finder. So I'll go ahead and bring it up. Oh actually before I do that I want to show navigation. So let's go ahead and select some stuff from the function pop-up. We'll do a command double-click. What's a good one? Read from URL so we'll Command double-click on that. We'll go to that method in here. You notice the button is indeed enabled.
We can go back to where we were. Now there's key bindings for that. You don't have to use the buttons in the file navigator. Those menu items are in the View menu. Go back, go forward. But we still have the ability to go back and forth through files and those you hold down the Shift key so if I hold down the Shift key you can see the menu items change.
We only have 1 file open so they're disabled right now. But this is another feature; I mean this has been around since you know the old Mac, Mac OS IX I don't know when it came in before then. But there's a number of menu items that are like that that have options.
Let's go down into the Find and you'll see that the Find command if you hold down the Control key turns into Find and Replace. Let's bring that up. So that brings up the incremental Find vander. As we type we can show it highlighting things as we go. If you hit return it goes to the next items.
Shift Return goes backwards through them. If you want to change the Find options those are in the Menu inside the search field here. So all the all the options that were there before are still here. If you want to do replacements those buttons are there. I brought this up in replace mode. But if you want to say make a selection replace only the items within that selection you do that by holding down the option key and you can see the button changes from replace all to end selection.
OK with that, I'm going to just switch this back to regular Find. So if you hit Tab that goes to the current selected item, bring it up again, actually let's go somewhere else and bring it up again. If you hit Escape you go back to where you were so if I went through those and hit escape it goes back to the old selection. So OK to review some of the shortcuts go to Definition Command, double-click, bring up Quick Help, is option double-click. If you want to go directly to the documentation viewer for for a symbol you hold down both Command and Option when you double-click.
I showed you control 1 and control 2 for the file and that function pop-ups. Actually there's 3 more pop-ups in the file navigator, maybe there's 4 I forget. They're all assigned actually to control number keys as well so you can get to all of those through the keyboard. So the go back and go forward menus are command option left and right arrow and previous and X file are the same thing only holding down the Shift key. Incremental Find as you're typing it selects something. Hitting Return sequences through all of the results.
Shift Return goes backwards. If you want to select the current result you just hit Tab. The finder the Find banner goes away. If you want to go back to where you were before you started this search you hit Escape. Alright with that let's talk about customizing the editor. So I showed you some text macros in action but let's show a little bit about how you define those and we'll also talk about user scripts. So text macros are defined simply as property lists. Each text macro is a dictionary.
So the different parts that you have to fill in, there's each each text macro has a unique identifier. Now if you want you can reuse one of the unique identifiers that's used by our built-in text macros and then you've overridden the built-in text macros. If you want the text macro to show up in the menu you can set that. There's a name for the text macro which appears in the menu item and in the code completion pop-up.
What gets inserted that's kind of important too, a text string. There's some variable substitution that's happening here and the infamous organization name is one of them. You can set the organization name in the Xcode UI, in the projects Get Info window and that's been in Xcode for a couple of releases now.
Finally if you want text macro to be available in code completion you need to set a code completion prefix for it. So these property list files. What do you do with them? Well you save them as files with a .xetxt macro extension. The best way to do text macros is actually to look at what's built in.
So we have a bunch of them, they sit inside of the Xcode application bundle inside its plug-ins folder. So this textmacros.xe text macro is itself actually a bundle and inside its resources directory is where you'll find all the text macros that are built in. When you install your own you put them into Xcode's Specifications Directory down inside your Home Library Folder. OK next I want to talk a little bit about user scripts. So there's a Scripts menu in Xcode.
There's a bunch of built-in user scripts that are there by default. Some of them you use probably all the time and didn't even realize they were scripts for commenting for instance, command/, that's a good one. So these scripts can act on the current selection in an editor or they can act on the document that you're viewing or they can act on the current project or they can act on Xcode or they can act on something else on the system. They don't actually have to be tied to anything. But the cool thing is you can edit them right in Xcode.
There is at the bottom of that menu is the Edit User Scripts menu item and that brings up this window here that on the left left is a representation of the User Scripts menu and when you select a script on the right you can edit it. With that let's show some of that in action.
[ Background sounds ]
OK so here's the User Scripts menu. We'll go ahead straight down and look at the user script editor. Make it a little bit bigger. You can see we have a bunch of built-in scripts. There's some very simple ones that do very simple things as shell scripts.
There's ones that do quite a bit more. You're never going to be able to see, that's actually pretty small compared to some of them. But this one's interesting because it's it calls out 2 Xcode using Apple script, I'm not going to go into details, to get some information which it then just uses in the shell script itself.
There are a few scripts that use Apple script directly and if you want to edit those Apple scripts you just click the button, takes you to the Apple script editor and you can edit it there. We're not going to do that right now. And I'm going to go ahead and add a very simple user script, a new shell script. Go ahead and change its name here.
That's I am just going to look at the environment. I know that seems uninteresting but it's what's in the environment that's interesting. So, so we'll look at the environment, we'll sort it make it a little bit easier to look at. So as input to this script it takes the current selection, that's actually important, the environment depends on what what you're selection is as you'll see and the output we're just going to put that into a new document. So this is all live, so let's select something here inside the editor.
We'll bring up the script and it was under text and show environment. So we now have this big list of things that were in the environment. You can see that we put some interesting stuff in there; the name of the file, the name of the project, lots of other standard stuff that's in your environment. There's a whole group of variables that control the formatting that Xcode does.
So this is used internally with Xcode's code completion, how it formats spaces in between parameters say in function calls that you've inserted, and it's also used by our built-in text macros, so we have a bunch of variables that are set there, you have access to them in your user scripts as well. There's a few items that show what's currently in the function pop-up which is kind of cool and down here there's the source context.
So what this is is Xcode's editor keeps a tree, the description of your file as you edit it and this is a description of what's in that tree. So we're currently the selection was inside an identifier inside a bracket expression and a block and a method definition and inside of a class implementation.
So that's user scripts. You can use all of that stuff yourself. We totally even encourage you to write your own scripts. Cool stuff. OK back to the slides and that's all for me. Next we're going to talk about building and debugging and for that I'm going to bring up Chris Hanson.
[ Applause ]
Thank you Dave. I'm Chris Hanson I'm also an engineer on the Xcode IDE team and first I'm going to talk with you about building your applications and how you can customize how Xcode does that. We're going to talk a little bit about the process Xcode goes through to build your apps and the customization points within that process. We're going to talk about how you can make your builds faster by leveraging Xcode's parallel and distributive build capabilities and we're going to talk about how you can automate your builds for continuous integration.
But first we really need to understand how Xcode builds your software. Now I often hear people talk about building their projects but in Xcode a project doesn't really build anything. It's just a container. It's more like a solution or a workspace in other IDE's terms. It's targets within a project that actually build your products like applications, plug-ins or frameworks and these targets are themselves composed of build phases that structure the steps that your build goes through, build rules that determine how individual things in your target are built and build settings that act as the knobs and switches that determine the exact settings that say compilers and linkers are passed by Xcode.
And a little bit more about these build settings; we all know that they're just key value pairs that act as parameters to your build but they're configured in configurations on a per layer basis. So Xcode actually has multiple layers: a target layer, a project layer and a default layer for build settings.
And build settings at the target layer override build settings at the project layer which in turn override Xcode's default values. And you can learn a lot more about build settings and how you can set them and how you can have them interrelate in the Xcode Build Settings Reference and Xcode Build System Guide.
When you create a new target you get a bunch of build phases by default. One of these is a copy bundle resources build phase which is really just a special kind of copy files phase and what it does is it takes assets that you've added to your target and copies them into your product's resources directory. Very simple. But you can also add other copy files build phases to your target either for organizational purposes or because you want to copy something somewhere else.
For example if you want to embed a framework in your applications frameworks directory instead of in its resources directory you would do that with a separate copy files build phase and this is the perfect way to embed frameworks and plug-ins within your applications. We've also generally seen people use run script build phases. For example this is how unit tests are run through the Xcode build system.
They let you run arbitrary tools and scripts as part of your build and when these tools are run Xcode will parse error and warning information out from their standard output and standard error and it will actually display it in the Build Results window just like it displays compiler warnings and errors.
But a little known bit about the run script build phase is that you can also specify inputs and outputs to them that allow them to participate in Xcode's dependency management. That means that if a build if a run script build phase is specified to generate a particular output and that output is already up to date Xcode won't bother to run that build phase.
So if you have a run script build phase that takes a long time it's worth it to set up the inputs and outputs so that it'll only run when it's actually necessary. And of course you probably don't want to put a huge amount of script code into the get info panel for a build phase. So as a pro tip you can keep your scripts themselves in separate files that you've added to your project and just invoke them from within your run script build phase and this'll actually let you use Xcode's editor features on your shell script.
It's not just for objective C C and C + + code. Now sometimes you might want to do something a little bit more open ended. Instead of just performing some scripted command let's say you get a bunch of art assets as postscript or other file format from your artist and you want those to go into your resources directory in a format that you can use for your tool bar.
Well you could sit there at the command line and process them all yourself and only check in your processed art resources but what if your artist gives you some more assets in that same format. You have to process them again. You could write a run script build phase that processes everything of that type and dumps it all into your resources folder but without setting up inputs and outputs you're actually doing a lot of work on every build.
What you can do is set up a custom build rule that tells Xcode if I have say a .PS file I know how to turn it into a .PDF file and here's how. And that will let you run an arbitrary script to perform that transformation and that transformation itself participates in Xcode's dependency management.
So it'll only happen when a resource in your built product is out of date and again Xcode will parse error and warning information. Now you don't just get the opportunity to run 1 phase that way. If you specify a build rule whose output is something Xcode knows how to process Xcode will process it.
So for example you can take a CSV file that contains level information for your iPhone game and rather than embedding it in your application as a resource you could write a script to generate some objective C source code from that CSV file so it's built right into your application at which point Xcode will see that the script generated an objective C source file, say I know what to do with that source file, I have a build rule for that, and it'll compile and link it into your application automatically with no extra work on your part.
You don't even have to add that generated source file to your project. And this works for anything Xcode knows how to build using build rules. It isn't just for objective C source code or even for source code. And of course you'll probably instead of writing your script in that small Get Info window you'll probably just want to have it call out to a script that you've added to your project.
That way not only can you use Xcode's editor features but changes to the script won't result in SCM changes to your project file. Now to make your builds go faster in addition to setting up appropriate dependency information on your build rules and run script build phases you can also take advantage of multiple cores on your machine. By default Xcode knows how to compile multiple files at once. And in Xcode 3.2 we've done a lot of tuning and leveraging of Grand Central Dispatch to ensure that Xcode only compiles a sensible number of files at a time.
Just because you have an 8 core machine doesn't mean it always makes sense to compile 8 source code files at once especially when you're dealing with heavily templated C ++ or the extremely memory intensive compilations. Xcode will monitor your system load, your memory pressure and things like that and decide how many compiles to issue based on that. But of course that only applies within 1 target. What if you have multiple targets that you're building? You don't always want to wait for 1 target to finish building before going onto the next one.
So you have to meet Xcode half way if you want to speed that up and actually specify the dependencies between your targets. But once you've told Xcode what targets depend on each other in their get info panels you can go to your project info panel and turn on build independent targets in parallel, at which point while you're linking 1 target, Xcode will just go ahead and start compiling the next independent target and it will actually order the compilations and builds of all of the targets in your project that are depended on by the target that you're building so that they happen as quickly as possible.
And finally most of us are on networks, have multiple Macs around and they're not always as busy as our machine is. So Xcode lets you turn on distributive builds through Bonjour or through specifying build hosts and lets you take advantage of multiple cores on your network, not just on your local Mac.
If you're working in a team situation you'll generally want to have a continuous integration machine always checking out and building the latest code from your source control and management system. We provide a command line tool Xcode build that can build targets within an Xcode project without scripting the Xcode UI and this can run headless.
So you can run this on a Mac mini with no display. You can run this on a X serve, a rack of X serves, it's all up to you. It lets you specify at the command line what target, what configuration, what SDK to use and it lets you override things like SDK's and build settings. It also lets you say I'd like to distribute builds to Bonjour or I'd like to distribute builds to a specific set of hosts.
For example if you're doing continuous integration and you want your continuous integration builds to turn around fast you might have a few Mac minis just sitting in a closet as a build farm and you're continuous integration system will only farm out to those minis rather than bogging down all of the machines on your network. And here we've just got an example of how you would invoke Xcode build. We're building the Zip browser target inside the Zip browser project in the release configuration but instead of building it fully universal we're just telling it to build for 32 and 64-bit Intel.
So now I'll show you a quick demo of some of the features of the Xcode build system and how you can customize them. I'm going to open a new version of Zip browser that I've added Apple Help to. Now Apple Help works by putting a help folder in your resources folder with an index in it that's generated by a command line tool.
So of course I've had to add this folder as a folder reference, and you can see that because it's blue and not yellow, to my resources. And to build it I'm also adding it to my copy bundle resources build phase. So I'm just going to open my build results panel and start building and set it to show all messages and hide this editor.
And you can see that this copy bundle resources phase is copying the folder. You can also see that it's running that I'm running a custom shell script at the end of the build. This script is this run script build phase. I'm going to get info on it and zoom in a little bit so I can see what the script is.
But like I've said in the pro tip this script just calls out to a script that's in my project. I'll close that and zoom back out and look under my scripts group and I have an index help.sh script in here that just takes some build settings from the environment which is how they're passed to run script build phases and tools in general. Changes into my built products localized resources directory and then just runs the help indexing utility on my help folder to generate a help index.
And if I run my project that I've just built you can see that I have not only a Help menu but that I actually have Quick Online Help and we can talk a little bit about customizing your debugging experience. Our debugger user interface is fairly customizable so you can see exactly what you want to see and how you want to see it. We also let you define data formatters for your own types so you can see just the information that's important without having to constantly twist down into your your variables display.
We give you executables through which you can customize how Xcode runs your application either through run or debug and we're going to talk a little bit about the access that Xcode provides to the GBD command line debugger. So in configuring the Xcode debugger interface we've generally seen demos of the in-editor debugging controls. These let you just start debugging regardless of where you are while your editing without taking you out of the editing experience.
They just put up a bar across the top of your editor with the most used debugger controls including controls that let you see what the stack is at any point where you're stopped and to see what threads are running. But if you also want to see a full set of variables rather than just hover over the variables you want to inspect or if you want to see the stack frame the stack trace always laid out for you, you can still use our traditional debugger.
But most of us have wide screens these days. Even WWDC now has wide screens in all of the rooms and a horizontal debugger display where you have the variables in the stack trace above the source code that you're trying to debug don't really give you a lot of screen real estate to work with.
So we also provide a vertical debugger layout where we put your source code side by side with your stack trace and with your variables. Of course you don't just have to look at your source code sometimes you want to look at both your source code and the generated assembly code and sometimes like if you're debugging heavily optimized code you just want to look at assembly and you can do that too in Xcode's debugger.
Now Xcode includes a technology called data formatters that let you see a summary of information in a single line about a variable of a specific type. And Xcode includes data formatters for a lot of common Cocoa types. But it obviously won't include formatters for your own types. So we provide a way for you to just define these as simple strings.
So here you can see a debug data formatter where inside some curly braces we have a debugger expression in the command language that uses $var to stand in for the variable that it's going to format and a :S at the very end to say that it goes in the summary field in the debugger's variable view. And you can learn a lot more about the specific details of the syntax of these in the Xcode Debugging Guide. But here you can see what they look like in action.
I've just Control clicked on this particular variable and chosen Edit Summary Format which is how you can edit a data formatter and the summary display column becomes editable and lets me enter in a data formatter. I've just entered in a data formatter that sends name to the variable and once I hit Return to accept this input, the debugger executes the data formatter in the context of my application and shows whatever it returned.
Now sometimes just evaluating a single expression isn't enough especially if you're working in a heavily multi-threaded, multi-core applications. So we also provide a plug-in interface inside xcode.app. Within our GBMI debugging plug-in there's a header file dataformater plugin.h that shows you exactly how you can create these debug data formatter plug-ins.
Now these don't run within Xcode, they're not Xcode plug-ins. What they are are plug-ins loaded by the debugger at debug time into your application. So they have access to your application's full state through normal language mechanisms. And because they're running inside your application while you're debugging it you do have to be extremely careful in them and the header file gives you the gory details of how you have to be careful about things like allocating memory.
But on the other hand because they're running in the context of your application you can take advantage of your intimate knowledge of your application state to do things like only look at variables when it's safe to do so from a multithreading perspective; for example when the right locks are held.
Xcode knows how to run your application for both running and debugging through what we call executables. These will show up under the targets group in a separate executables group and the Xcode groups and files tree by default and they let you tweak how Xcode runs and debugs your app by letting you specify command line arguments, environment variables and a working directory.
This is how you set up debugging for your unit tests and it's also on Mac OS X how you can set up remote debugging over SSH. Finally, Xcode provides a debugger console that doesn't just provide you access to your application's standard input and output but also provides you access to the full GDB command language.
So you can do anything in this console that you can do in GDB generally and you can create macros for really complex queries. Here I'm showing Xcode's provided info GC routes macro which simply examines the objects that still have references to another object while you're running under objective C garbage collection. So let's see a quick demo of some of the debugging features in Xcode 3.2 and I'm going to open yet another version of Zip browser, this time one that I've added some unit tests to.
[ Background sounds ]
Now I'm going to bring up the build panel. I've just used the Command Shift B shortcut to do that. I'm going to get rid of the in build panel editor I'm just going to click Build. To build and run my unit tests. So of course it built my it built my application first and then it's running it's building and running my tests and you can see here new in Xcode 3.2 we're showing the output of the unit tests in the build results without forcing you to look through a transcript. You can also see that we have a failing test here and not only is it a failing test it's a failing test whose failure message extends a little bit far to the right.
But we have this convenient More link that if we click it, it expands our result to multiple lines and of course we can get rid of that by pressing Less, I'm going to keep showing the whole thing. And of course once we click a result it also brings up the embedded editor because we have Xcode's auto open embedded editors setting turned on. This will be a very simple test to just fix but I'm going to actually show you how I would debug it. I'm going to set a break point right here.
I'm going to close the window though and show you the executable that I set up and you can see that I've added 1 argument for unit testing and a few environment variables and these are documented on the ADC website. Now if I just bring up the debugger I'm going to make this window a little bit larger and debug with break points on.
I'm going to stop at my break point. I can see I've got my stack trace over here, my variables over here and I can also hover over my variable and I can see that it's untitled with a U but what I'm comparing it against is untitled with a u.
That's obviously going to fail so I'm just going to stop this, fix it, Save, Build and Debug and I get right back to where I was. If I step over it I can see in my console that I don't have any test failures. And we can see in the summary format if I just build and debug 1 more time that name actually has a summary of untitled. If I chose at its summary format we can actually see the data formatter that's invoked to produce that output. And Andrew is going to tell us a little bit about source control management and snapshots.
[ Applause ]
OK. So I have 3 things I'm going to talk about in my portion of the presentation today. I'm going to start with the SCM autoconfiguration feature. Then I'm going to go on to the multiple project roots feature and finally I'm going to talk about 2 different kinds of visual comparisons you can do with snapshots and Desk CM. So we'll start with autoconfiguration and it's easier just to show you so we'll go straight to the demo. So helping me with the demos today is Justin Gareau, Xcode QA. OK so in order to use the SCM autoconfiguration feature we have to turn it on.
So we'll show you where to find that right now. Go to Execute Preferences, scroll over to the SCM pane then select the Options tab and there's the check box for configure SCM automatically. So let's check that. We can just click OK. So now let's open a project that's been checked out from a SCM repository.
For that we'll go to another version of our Zip browser project and all we need to do is open it. OK see if you can make the dialogue there a little bigger. You can see that when we open a project that's been checked out from a repository in this case Xcode prompts us for the fact that it wants to add information about that repository to Xcode's preferences. You can see that Xcode realizes it's a subversion repository.
Xcode also supports CVS and Perforce and there's some other information about it as well that Xcode knows. Let's just click Create there and we can make it smaller again and you can see if we go back to the Preferences window that Xcode has added information about that repository to our repository configurations list and so we can click OK there.
And then the project itself has been set up to use SCM from this repository and also as a convenience the SCM column in the groups and files tree of the project has been made visible. OK, so the second thing I'd like to talk about is multiple project roots in Xcode.
This is the multiple aspect of it is new in Snow Leopard and Xcode 3.2. But in order to explain why multiple roots are a big deal I need to first start answering the question well what is a project root? So a project root is quite simply a directory on disk; a directory that represents your project, that contains your entire project.
The project file, your source code files, your resource files, everything. Now why would we need this sort of a concept? We need it because of some features that were added or revamped in Xcode 3.0 and these features operate on a file and directory level instead of on a project level.
Source control in snapshots we're talking about today. The project Find Symbol option you can try for yourself but we won't talk about it very much today. So, to sum up, a project root is a directory containing all the files in your project used by these features in Xcode and its drop dead easy to use.
You've probably used it yourself without knowing it if you've used SCM or snapshots in Xcode 3.0 or greater and that's because the default value for your project root which is just the directory that contains your project, is usually all you need by default. So why would you want to use multiple project roots then? To explain that I'm going to show you a particular scenario. In fact a directory layout that should be familiar to many of you already.
It's the layout you use for cross platform efforts. Now let's go through this. The very top level directory contains all of the subdirectories. There's also a common directory for cross platform logic or utilities and then there are the directories for each of the platforms. In our case when you're using Xcode the one you care about is the Mac platform.
But you would also have a directory set up like this if you're doing Mac and iPhone development together. Now if you can only set 1 root for your project and you want to operate on the 2 directories that we care about, Common and Mac, you need to set that root to the very top level directory, the source directory. But that means that all of those operations would take place on all of the subdirectories, even the ones you don't care about.
So for multiple roots you can say well I want Common and I want Mac and that all of those operations would just take place on them; check outs, making a snapshot, and you wouldn't even have to have the other directories on your computer at the time. OK, so that's multiple project roots so let's see them in action. We'd like to add some additional project roots to our Zip browser project.
In order to do that we'll bring up the Project Info window. You can make that a little bigger there and that will let us see the project roots UI for the window here. You can see there's an area for roots available. There's only 1 there right now and there's also the button for a configure roots and SCM. Let's press that now and that brings up a sheet which lists all of the project roots for your project. We've only got the 1 right now; the default.
We're going to add some extra ones, we'll click the OK button or the Push button there and we need to navigate to our to the same directory where we have our Zip browser project and that has some other directories in there for sample files we might use for a demo. JAR files and Zip files. Let's select the JAR files directory and open that.
And you can see that brings up another dialogue, that's because the JAR files directory was actually checked out from a second repository, different than the first one. That's one of the things that's possible with multiple roots and it has some information there about the new repository. Let's click Create and now we see that we've added another repository configuration to our preferences. Let's click OK there.
OK so we have a second root. Now let's add a third root for our Zip files directory of sample files. You can see that this time when we added the root we weren't prompted again because Xcode already knew about that second repository and could just apply it to the new root.
[Cough] Excuse me. So we click OK there. OK now there's 2 things to note in the UI here. One is that we now have several roots listed instead of just one. The second thing is that there's now a warning about our project format and this is because the feature of multiple project roots is only available in Xcode 3.2 file format.
But we're still using 3.1 format. So we need to upgrade that to 3.2 and that makes the warning go away. OK so we can close that. OK so the third thing I'm going to talk about today are 2 kinds of file comparisons. 1, snapshots and NIV comparisons and 2, SCM and project file comparisons.
Excuse me.
[ Background sounds ]
OK so before we can tell you about [cough] excuse me. Snapshots and NIV comparisons we need to make sure that we can answer the question what are snapshots? How many of you have used snapshots in Xcode? OK so some of you. Not necessarily a whole lot. Snapshots were introduced in Xcode 3.0 and we made a lot of stability improvements to them in 3.2.
If you haven't used them already I urge you try them out. But to understand what snapshots are you need to think about undo and redo. These are things you do every day in Xcode documents and documents in other places in OS X but the key thing about them is that they only work on 1 file at a time.
If you have changes to multiple files like what you would see from refactoring changes in Xcode or from the new project rename feature that was introduced in Xcode 3.2 you wouldn't be able to hit Command Z to undo all of those changes because we operate them 1 file at a time.
For that you need snapshots. Snapshots are essentially multi-file undo and the way that they do that is before you actually change the files for factoring or project rename their going to copy all of the files in your project from your project root or project roots to another location.
That way if you say later well I've got to get that state back you just restore the snapshot and all those files change back to what they were before. Now where is that information copied to? You can see up here there's a long path ~Library/Application Support/, Developer/SharedSnapshotRepository.sparseimage. That's the name of the path and the name of the disk image that snapshots use by default as their copy location.
Now you can change that location to another hard drive or to use your own encrypted disk image if it's got sensitive content in there, using the XCSnapshotDiskImagePath user default, you'll have to change that at the command line, there's currently no way to do it in the Xcode IDE. Now for both of these pieces of information there are documents that you can read about it in. Xcode Source Management Guide, which I recommend you all read. It's got a lot of information about snapshots and SCM and the Xcode User Default Reference for the user default.
OK, so now let's look at these comparisons. First I'd like to show you where you can find that UI that I was talking about, excuse me, the features that I was talking about before that use snapshots. You can find refactoring by going to the edit menu and there's a refractor menu item there that will only be active if you have a valid selection in a source code file. And you can also see the project rename from Project, Menu and then Rename. Ok, but for our purposes today we want to look at snapshots and we will do that by bringing up the Snapshots window.
OK and you see that there are 2 snapshots that we've made here and let me make that window bigger here first. There we go. OK and you can see that well let's select the 2 snapshots because we actually want to compare them against each other and then the files list to the right shows you what files have been changed, what files have been added, what files have been removed between the 2 snapshots.
We're interested in the files that have changed and can we see that OK here? The 2 new files that are listed as being changed have rather odd names: keyed, keyedobjects.nib, designable.nib, these aren't names of new files that you normally deal with yourself and the answer to this issue is found by looking at the path for these files.
We find that these are actually sub-files inside of the main menu.nib wrapper file. Now for features like snapshots and SCM they don't really deal much directly with wrapper files they deal with the actual files on disks, the sub-files underneath those wrappers. But what we want here is to actually see the real meaningful differences between these Nib files.
And snapshots comes through with us here. So let's select one of those 2 sub-files [cough]. So what you'll see here is some text that probably doesn't ring any bells for you. That's because what Xcode actually does here is take those 2 wrapper files, run them through IV Tool, get the textual output and then compare the 2 against each other.
That output is not a documented format, so it's not something you would normally need to completely understand or be able to change. But here what you can do with it is get a general sense of the meaning of what's changed and so if we look here we can see that the difference between the 2 files consists of menu items.
Here click Zip browser. You can go down to the next one, Zip out Zip browser. So this way while you can't necessarily know what these formats do you can say OK the difference between these 2 what I would say type into a SCM comment if I were checking it in is menu item changes. So that's how snapshots helps you with NIB file comparisons. OK so we can close that. Alright and so the last thing I'm going to show you today is project file comparisons under SCM.
So let's look at the SCM results window. OK so we can see that there are M's for modified for both the local column and the repository column for the ZipBrowser.xcodeprojfile but that's actually a wrapper file so we need to dig into to find the real sub-files there and the sub-file we want is project.pvx.proj. Now so there are changes remotely and there are changes locally that may lead to a merge conflict if we were to update our local repository.
So we want to look at the comparison of these 2 versions of the project file to see if that's actually going to happen. And so yes we can go to SCM compare with latest to see that comparison window. OK now this comparison is a lot like the Nib file comparison. It's an undocumented format that you can still gain some information about by looking through it.
So the object version isn't something that's all that important. We can go to the next one. Here we can see that the remote version on our left has reference to new file tarreader.eb. Now what that means is someone added support for Tar archives to their version of Zip browser, expanding what it can do.
Now the next one that you can see is that it also refers to tarreader.h, tarreader.m. So these are new files that the project is referring to. If we keep going down now we can see some changes on the right as well. We can see the update to the project file format and the addition of the project roots.
We go down a little further and the last changes to the file are other addition additional file references here but the key thing to understand about this comparison is that none of these files are contiguous and what that means is that our SCM system is going to be able to merge the 2 sets of changes without any conflicts.
So let's do that now. We can close the comparison window and we can choose SCM, update entire project. And so we have to reload the project from disk, but once we do that we can see that our local changes have been preserved while the new references to the TAR reader files have been added. The merge has been completed successfully.
OK, so in summary, going through some of our goals here. We've shown you how to tune Xcode to your liking by doing things like adding macros and key bindings to your text editing or flow and adding custom build phases to your targets. We've shown you where you can find things like Xcode's snapshots copy location and how to use tools like Xcode build for your automated work flow and we've shown you how to be more efficient in Xcode both by having Xcode do less work such as by setting multiple roots or by you doing less work by being able to find the problems in your project by debugging more efficiently. So we hope that you've enjoyed this session.
[ Applause ]