[ Silence ]
Anders Bertelrud: Welcome to session 401, Xcode Core Concepts.
I'm Anders and later on in this session I'll be joined by my colleague Rick.
So, this morning in Presidio in the previous Xcode session we saw what's new in Xcode 5.
And in this session I like to talk a little bit more about the core concepts behind Xcode, both those in 4 and also those that are newly expressed in Xcode 5.
And the goal is to give you better understanding of what you're seeing in the UI and to make you a lot more efficient as you're using Xcode.
So specifically we're going to start talking about the user interface and the various concepts behind that with the special focus on navigation.
When you're working with your code, a lot of the times you're going back and forth between various source files or UI files.
I want to make that as efficient as possible and Xcode has a lot of good features for that.
We're going to talk about working effectively with editors, with the single editor as well as multiple ones.
We're going to talk specifically about some of the things in the source editor that you can use to be more productive.
I'm going to talk a little bit about documentation integration, and how to customize Xcode's behaviors.
Xcode has fairly flexible behavior system that you can use to really improve your workflow.
After that, my colleague Rick's going to come up on stage and talk about the fundamental concepts that underlie Xcode, the once you're manipulating through the UI.
That includes workspaces, projects, targets, schemes and run destinations.
So some of this will be familiar from Xcode 4 but there may be a lot of things there you don't know about and some will be new in Xcode 5.
We'll start with the UI.
This is the familiar Xcode workspace window.
And so I won't go into it in detail because you all have seen it before.
But briefly, to the left here is the navigation area.
All of that area are consists of different panes that show you a different view into your code.
I should say also on the right there is the utility area consisting of the inspector on the top and library at the bottom and in the middle is where you do the editing, and of course you can close any of these panes.
So let's start by that focusing and navigation.
So the navigator area here on the left, the very top of that are the selectors for choosing which navigator you want to see.
We'll go into each of these in a bit more detail.
We have the project navigator, the symbol navigator, find, issue navigator.
The new one in Xcode 5 is the unit test testing navigator, debugging and related is breakpoints and then of course the log navigator.
So taking a closer look at those, first of all, I want to show that at the bottom of most of these, we have a filter bar that's down there at the bottom it's different, slightly different for each of the navigators but it fills the same function for each.
There's usually a way to create the new entry of the content that you're looking at, whether that's a file or breakpoints or any of those.
There are state filters that are specific to the particular navigator you're looking at.
And then there's usually, most of them, have a generic text filter, where if you know the name or a substring of the name of what you're looking for, you can just type it in and quickly narrow down on what you're looking for.
So, looking at each the navigators in turn, we'll see first here with the project navigator, there is a recently edited, first of all, of course it shows you the project contents, projects, files, those kinds of things.
At the bottom there, there is a recent filter and this could be very useful if you have a very large project and you've been working on a certain set of files, you have a certain working set.
So those will show you the ones you've been visiting recently.
The modified filter will focus just on those things that you modified since the last time you checked anything into source code or that have interesting SCM state.
And of course there is the filter field where you can, in this case, we type in the string render and we see just the entries that that contain that name.
So that's pretty simple.
Now the symbol navigator, it shows you all kinds of symbolic information that we get from indexing your code.
So this includes of course classes, methods, enumerations, all those kinds of things.
There are filters there to let you focus just on your own or the ones that are in the system as well.
The find navigator is where you do workspace wide searching of either regular plain text strings or regular expressions.
And so one of the things that you can do here is to go into replace modes, you could do search or you could do replace.
And as you saw yesterday we in Xcode 5 we streamlined the UI here to make it a lot easier to get at these various things.
You can actually delete search results, as you go through them, and that doesn't delete them from your code, it just takes it out of the list of the ones you're operating on.
There's also a scope field and what that lets you do is to narrow down the search or replace on just a particular part of your workspace.
Now that could be either a subtree or subfolder or a project, or you could define your own filters that define a set of files such as all header files or all nib files.
The issue navigator shows you issues that Xcode has discovered with your project.
So this could be, of course, warnings and errors form the compiler or linker, but also static analysis results.
And also Xcode itself, you before you build will check for certain consistency issues, such as if you don't have the right SDK installed that you'll need for the project, you'll see that right away.
And sometimes, if Xcode detects a modernization suggestion, it will actually tell you here as well.
So that's a good place to check and try to keep this as empty as possible.
The test navigator is new in Xcode 5 and this shows your unit tests and that also let's you create new ones from here and run them, and there's a whole session about that coming up and so, so I won't say much more about that here, that's on Thursday.
The debug navigator is of course where you see the current state of your program, that's where we have the new gauges in Xcode 5 and there's a whole session on that as well, so I will skip over that one as well because there's a lot more to talk about in this session.
That debugging session is on Wednesday.
The breakpoint navigator is closely related to the debug navigator, and unlike the debug navigator, this is one where you can create content even if your program is not running.
So for example, you can create new breakpoints, new symbolic breakpoints or just breakpoints in your code.
One of the new things in Xcode 5 is that this pane shows you the resolved breakpoints of any symbolic ones you have.
So you can enter symbolic breakpoints for a certain method name and then you can see all the places that match that in the code and, and click on them to go directly there.
And of course the activity log navigator, that shows SCM activity, it shows you build, warnings and errors and those kinds of things.
And in Xcode 5 it also shows you the diagnostics and logs that you get from your Xcode service bots.
There's a whole session on that called "Continuous Integration in Xcode 5" and that's going to be this afternoon at Presidio.
So, because these are very commonly used and very useful different entry points into your code, they have very convenient keyboard shortcuts.
So control simply 1 through 8 will put the cursor in the navigator, switch to the right one, put the cursor in there so you can use the arrow keys to go up and down and then quickly go to the file you want.
So even if your hands are on the keyboard, your text's you're looking at your text, this is the the way to do that.
Let me just very quickly go there.
So let's talk a little bit about editors and working effectively with editors.
We've seen now how to navigate between the different content and get different files into the editor.
So at the top of the editor, on top of every editor, there's a jump bar as we call it, and it has various components.
So, there's the the related files menu, I'm sure you've used before but I hopefully I can show some, some extra tricks on how to use that.
There's back and forth buttons, each editor works a little bit like web browser in the sense that there's a history, you go back and forth not only between files but also the locations within the particular file.
The location of the file in the workspace does two things.
It it tells you what file you're editing especially useful if you have multiple files with the same name, but also it lets you access any of the other files reachable from your workspace.
And on the right here is the issue mini navigator.
If you have any issues at the issue pane that are associated with files, you can use the arrow keys to go back and forth between them or pop that menu and just cycle through the, the issues and fix them.
So, the starting off from the left here, we can hit control 1 or we go, we click on the, the menu.
We get to the related files menu.
And when Xcode indexes your project it knows a lot about each file and how that can be related to the other one, so obviously there is a recent menu.
Counterparts include most obviously if you're looking at the implementation you can see the header, vice versa, superclasses, pretty straightforward, categories, and those kinds of things.
Now, there's also a convenient way to get to any other file that this file includes or vice versa to get to any other includers of this file.
That's great for a header when you're wondering which other files include it and you want to go quickly between them.
And then of course, new in Xcode 5 is that you can get to tests as well.
At the bottom there are controls to get to preprocess and assembly language outputs of your current file.
And when you do that you get a preview of the assembler and you can pick if you have let's say code that compiles both for iOS and for OS X, you can pick which CPU you want the assembler output for.
The back and forth buttons are pretty straightforward.
I won't spend a lot of time on those.
But there are keyboard equivalents for each of these and, and so that will conveniently get you up to the menu.
The menu that shows you the entire workspace can be quite big but it uses submenus to let you navigate really to any file at all that you can reach from the workspace, so that can be fairly convenient.
And then finally, if you if you hit Control 5, you get to the menu that shows just the files.
Very often the other file you're looking to go to is up here of the one that you're already viewing and so control 5 put you on that menu, you can use the arrow keys and return key to quickly go to any one of those files.
And control 6 pulls down to Symbol menu which is, well, shows you all the classes and methods.
And one of the tricks that actually works with all these menus is type-aheads.
You can just start typing when you're looking at any of these menus and it will quickly filter down to exactly what you're looking for and that can be that actually works in all of them and that can be a great way to just very quickly get to the menu you want.
So, we've looked a little bit about the jump bar at the top of editors.
So let's talk about the assistant editor, when you open up Xcode by default, you get just the single standard editor, and whenever you choose a new thing to look at though navigation, then the content is replaced.
Now, the assistant editor is a secondary or it can even be tertiary that opens up and it will track the contents of the primary editor.
And so this is excellent for looking at auxiliary content.
And one of the things that you might not know is that you can you have several options for how to lay out the assistant editors.
They can stack from top to bottom, or right to left, et cetera.
So with the Assistant Editor, how do you invoke it?
One of the ways you can invoke that is most obviously with the tool bar and you see here the highlighted button there, it gets you into standard editor mode, just clicking on the assistant editor button put you on assistant editor mode.
You can conveniently access any kind of SCM information about the current file as well.
And for each of this there's, there's key equivalents you can see in here, command Option, command Shift, et cetera.
There's a whole session on SCM and Xcode and that's going to be on Friday in Pacific Heights and that will talk a lot more about the functionality that you get underneath that, that mode.
Going back to the Assistant Mode here, regardless of how you invoke it.
What happens when you invoke it is you get a second editor that tracks and by default it will track whatever is most appropriate as a counterpart to the file and the primary editor.
Xcode knows things like header files being associated with implementation files.
It also knows for example that a vertex shader is associated with a fragment shader.
So when you choose counterparts here, it will go between the various, various files and when you switch a file, the assistant editor tracks.
This is particularly useful when you have contents such as a nib file.
So if you're looking, for example, at a view controller, you can see that the corresponding UI in the right hand side there.
And then what happens when you're looking in the assistant editor is you may very well want to actually focus on that for a bit so you can choose the to make that the primary content.
And what happens in that case is that the assistant content becomes the primary content, and now the assistant editor is available to show you related content to that.
So that way you can sort of navigate back and forth in your graph of connectedness between your files.
In this case, as you click in the nib file, you can see the source files that are related to the various doc various objects in your nib file.
And you'll notice that the Assistant menu now has changed to show you entries that are relevant to the nib file.
So you can very easily, for example, go through all of the different actions that are, that are presented in this nib file.
In activating the assistant editor, how do you do that?
Well one is of course, you can use the button in the tool bar, but there's a very useful thing throughout Xcode, and that is the Option key where when you use the Option key, and combine that with other modes of navigation, instead of putting the source file into the primary editor, it'll open up an assistant, and this could be very useful.
It exists in a variety of places.
So for example, command click on a symbol will navigate to the source of that symbol to to where it's defined.
If you also hold down the Option key, it will do the same thing but open up an assistant editor.
And you can do the same thing when you click on a File and then any of the navigators, hold on the Option key and it will instead put that content in the assistant.
And that can be very useful when you're navigating and you don't actually want to focus on what it is that's that you're seeing, you just want to keep it up as auxiliary content to maybe for reference.
And in addition to that, if you want even more power, if you hold down the Shift key in addition you can get to the navigation chooser.
You can also get to it from the menu, the Open in menu.
But again, Command, Option, Shift will bring up the navigation chooser.
This is a HUD that lets you use arrow keys and return key to really do anything you want.
You can put the content in a new tab, you could add a new assistant editor or you can even create a new tab, it will put in an existing tab or put content in a new window.
This is very customizable and the user, perhaps you can set exactly what happens when you hold on the option key, when you double click, et cetera.
So if you haven't customized this you may want to take a look at that and see if you find a better workflow for you with these options.
All right, so another way to navigate is open quickly, and I'm sure many of you use this.
Command, Shift, O, brings up open quickly, and here you simply type the name or a part of a file or a symbol and Xcode narrows down the list.
And as you notice, you actually don't have to type the contiguous range.
Very often if you just remember the first parts of various, of the subwords, you could type that.
And very quickly get to where you want to go.
And also the Option key works here too, so if you just hit return now or just select this then you'll be replacing the content of your primary editor.
If you hold down the Option key as well, it'll open up assistant editor.
So let me show you few things about the source editor.
So that's couple things about the assistant editor and the key takeaway there is the, the power of the Option key, it can really, really help you with your workflow there.
With the source editor, there are couple of things there a lot of features, but a couple of things I want to call out in particular.
It's very common to want to rename all the local variables, a a local variable, all the occurrences of a local variable to, to have a single name.
So, you can do that by editing each occurrence of it, but a better way is to do Edit All in Scope and there's a menu item for that but there's also command, Control E.
And when you do that, what Xcode does is to take what's under this the cursor, and there's actually a submenu that shows up underneath an arrow there.
You can so there's variety of ways to invoke it.
And then as you just type, Xcode will replace all the locations of that same symbol.
And it's not purely a textual replacement.
It uses the index and it knows that two variables with the same name are actually different if they're in different scopes.
So that that can be a really great way to rename a variable to, to have a better name if you picked the wrong one the first time around.
Another very useful feature is Code Snippets.
So, very often when you're coding, you come to a point where you say, "Well there's a sort of, the sort of pattern here of function call or a loop that I want to use."
And Xcode has a fairly large library built in Code Snippets for common idioms into various frameworks.
One way to instantiate it is to just drag and drop.
And then what you get is you get tokens for where you're going to fill in your own content.
And you can just fill that in and then just have your own your own code there.
But very often, you will have your own code where you want to create your own shortcuts for it.
So you can also create custom Code Snippets, and to do that, you just select a bunch of code and then you drag it over and drop, and you see that it shows up right there on the on the side.
A popover comes up and it will let you edit any of the content in here.
So there are menus to let you choose the platform and the scope and the language, that's pretty straightforward.
You edit the contents of it and I want to call out one thing in particular, when you edit the contents, you can use the syntax that uses angle brackets and hash marks to surround parts of your text that you want to tokenize.
So those then become tokens when you instantiate the Code Snippet that can be easily replaced.
That turns into a token, and then you can also crucially, you can set a code completion default because as fun as it is to drag code snippets, you probably don't want to keep the utility area open, and certainly you don't want to reach for the mouse in order to do instantiate a code snippet.
So, by associating a substring here, now it becomes avail and I'm hitting OK, I'm done.
Then it becomes available when you go down and put your cursor in the code, and you can instantiate it.
And when you start typing, code completion will include that code snippet.
And then when you instantiate it, it shows up and you can just replace it.
So, with that I'd like to invite my colleague Rick on stage to show you some of this in action.
Rick Ballard: OK, thanks Anders.
So, right now I'm going to take you through a quick demo of using some of the features that Anders just talked about to work efficiently in Xcode.
All right, so, I've got my project here and I have a problem I want to investigate.
So, first of all I want to go look at the method where the problem is.
So, as Anders told you, you can just use Command, Shift, and O to bring up Open Quickly and start typing the name of any symbol in your workspace and we'll find it via the index.
So, in this case, I'm going to start typing part of shape class and it found my method, register shape class with tag, and I just hit Return and here's the method that I want to take a look at.
So, this method is dispatching something to a concurrent queue.
And the problem I have is that one of the callers of this method is passing nil for one of the parameters.
So, this is assert is firing.
Now normally I'd just look at the backtrace of my assert to see who called this the wrong way.
But since this is dispatched to a concurrent queue, that backtrace just shows dispatch machinery and I can't see who's calling my method with a bad parameter.
So, I'm going to use the power of the assistant editor and our callers functionality to track down who might be causing this here.
So, first of all I'm going to go ahead and select the assistant editor in upper right-hand corner and I can go and see a bunch of different related content in the assistant editor.
In this case I'm going to go take a look at callers, and here Xcode through its index has found everything in this workspace that calls this method, there are three callers.
So, now I can easily just select one of them and here I can see this method is definitely not passing nil for that parameter.
So, this is not the problem.
So to go to the next one, I'm actually going to use a keyboard shortcut now.
If I use control 4 it will pop-up the assistant menu again.
And I can just use the Arrow keys and select the next caller here, and I see this one also is not passing nil for that parameter.
So, I'm going to do that one more time, I'll select the last caller and this one is has forgotten to pass a tag.
So, there's my problem.
So, I can just say fill in this fill in this tag and I fix that problem.
OK, I'm going to go back to my standard editor so you can see well here.
And the next problem I want to solve is I have this property isLoaded here and I maybe want to give that a bit more of a descriptive name.
That property reflects whether my cache is loaded.
So, I think I actually want to call it, isCacheLoaded.
So to rename a method, normally I could use to use Xcode's refactoring feature to rename a method and it would rename that method and all callers of that method.
But in this case, this property is, key-value observed by some of the callers and so this method name or this property name just shows up in string values to key-value observing so the rename refactoring isn't sufficient.
So, for this case, I'm actually going to use a textual find and replace in order to rename this method.
So first of all I'm going to go to the find navigator, command 3 will bring that up easily.
And I'm going to select the word "Loaded" that I'm going to replace here.
Command E will put that in the find pasteboard.
So, you see it's showing up here in the upper left-hand corner.
And if I hit Return, I can find all instances of the word loaded in source code in my workspace, just like that.
So, I actually want to do a replacement here.
So, I'm going to choose replace then I want to replace the word Loaded with cacheLoaded.
So, if I hit replace on that it will go ahead and make this change.
But before I do that, I ought to make sure that all these instances of the word loaded are actually references to my property name and not that word showing up somewhere else in my source code.
So, if I start flipping through these, I see, here's a case where that property is being key-value observed.
Here here is that key path again.
Actually, almost of these are my property, but there's one that isn't and that's the underlying shape cache isLoaded property.
I'm not renaming that.
So, I don't want my find and replace to touch that one.
So as Anders said, you can actually delete find results out of the find navigator.
So, with this selected, if I just press the Delete key, it deleted that find result.
And now when I do my batch replace, it's not going to touch that one case.
So, I can just replace the instances of the string that I want to.
So, I'm going to say replace all, I'm not going to use snapshots at the moment.
And now, it's gone ahead and renamed our property to isCacheLoaded.
All right, there's one more thing I want to show you.
I have a method that I want to validate that some other methods that I call are doing the right with change management.
So, first of all I'm going to go back to the project navigator to find this file.
I could use open quickly again, but I'm going to show you a different way.
Down in the lower left, if I select the recent files filter, you'll see just the files that I've been editing recently.
And this provides a really nice working set.
If I'm going back and forth between a few files I edit frequently, I can just see them all here and have them all immediately accessible.
So, in this case the file I want to edit is SKTDocument.
And now, I need to find the method I'm looking for so I'm going to use control 6 to bring up the symbol pop-up.
And with type-ahead, I can just start typing what I'm looking for.
So, I'm going to say readFromData.
Here it is, there's the method I want, I select that, and here's the method I want to take a look at.
So, down here this method is removing some graphics and then inserting some graphics, and I want to make sure that both of these are doing the right thing.
So, if I command click on this symbol it would jump right to that method and I could see what it's doing.
But in this case, I actually want to see my code side by side, so I can see that it's all coordinating properly, so to use that I'm going to use the assistant editor.
So as Anders said any navigation that you can do if you add the option key, it will send that navigation to the assistant editor.
So, instead of command clicking on this, I'm going to command option click on it and that will automatically open up the assistant editor and you can see here's the method that I want to take a look at.
So, that's great.
I also want to look at insertGraphics at the same time.
So, I'm actually going to open up another assistant editor to do that.
So, Anders mentioned that Option, Shift, Navigation brings up the navigation chooser and let you choose where your concept will go.
So, I'm going to Command, Option Shift, click on this method.
There's my navigation chooser, I can just go down and tell it that I want to open a new assistant editor, hit Return, and here's this method opening in a new you open in a new assistant editor.
So, I can go down here and see that my remove method, before it does the remove, it stops observing graphics.
My insert method, after it does the insert, it starts observing graphics.
So, this looks like it's all behaving correctly and works the way I want.
So, that's just a quick example of how you can use Xcode's navigation features and our assistant editor to build really efficient nice workflows.
Let's turn it back over to Anders.
Anders Bertelrud: So, let's talk a little bit about documentation integration.
Xcode 4 had good documentation integration, and in Xcode 5 it's even better.
One of the ways, of course, when you want to look at documentation is you're looking at your code, you have your hands on the keyboard, and you may want information about a certain method.
So, in Xcode, we provide documentation with the command completion.
So, when you go to complete code, you can now get information about the item under your selection.
If you have more than one as you arrow up and down, you get a short summary.
This is great if you don't know exactly which method you're using, that you want to use, then you can get a summary of it.
Another thing you can do is to option click and that will get you, instead of command click goes to the definition, option click will get your documentation about the symbol under there.
And as you can see, we have complete documentation about the symbol without even having to open up a utility area or documentation area.
That's great when you just want to know some more information about a particular method that you see being used, method or function or enumeration, et cetera.
Sometimes though you want to look at documentation a little bit more permanently or less transiently, so what you can do there is to open up the right side of the utility area there, and then keep that open, and as you move the cursor around, the quick help will show you the information about whatever is currently under your cursor.
So as you use arrow keys up and down for example the content there will change.
So, that's all great.
That's for the built-in documentation for iOS, for OS X, SDKs, etceteras.
So, what about your own code?
Well, this is what you see if you haven't told Xcode anything else, all it knows is where you declare it which would be in a header file usually.
But, as you may have seen in the previous sessions, in Xcode 5, you can do better.
So, this is how your declaration looks without any other adornment and that's the help you get.
You sort of get what you put into it.
If you put some comments in, for regular comments, you can put some special annotations in there, Xcode will parse that, in this case we're using doxygen type tags there, and then Xcode can actually show a pop-up that will give you a lot more information.
The same amount of information that you get for the built-in SDKs.
So, in this case for example, you see how the various parts of your comment translate to the various parts of the pop-up.
And you can get more information about the syntax, at doxygen.org.
So, now if you go back to our source code, when we try to use code completion on our own method instead of just the header we get full documentation and of course we get the same thing with the option click for the pop-over, and we get the same thing in the quick help on the right side of the screen.
So, that way, you can really make your own code for your own sake and the sake of your teammates be as well documented as Apple's APIs are.
Let's talk a little bit more about the documentation window.
You've seen this one before I think also in the Intro to Xcode 5.
In Xcode 5, we've pulled the documentation viewer out of the organizer and put it into its own window which and along with the new great multi windows full-screen support can be a great way to put your doc on one window, et cetera.
The documentation viewer now let's you look at the content and also the Table of Contents on the right for whatever document you're looking at.
And also whenever you see anything that you want to highlight that's particularly relevant to what you were looking at or what you need to work on, you just click on the Bookmark icon and then that entry shows up in the bookmark pane on the left where you can very quickly access any part of the documentation whether it's a method or conceptual documentation or anything like that.
And of course, you can close both of those sidebars to see the full documentation experience when you really want to read a particular document.
Finally, I want to talk a little about and this is finally you have UI part of this.
I want to talk about how you can customize Xcode's behaviors to increase your efficiency.
So Xcode has a lot of filters features built in, and there are also a lot of triggers that you can associate custom behavior with.
So on the left side here, this is in the PrefPane, and you may have seen this before, you may not.
In the PrefPane, there are a bunch of built-in triggers of various kinds when your program hits a breakpoint, when your program crashes, when you check something into SCM, you can associate those with the actions on the right.
And so there are several built-in actions.
One of the ones I want to point out which you might not be aware of is one that works in conjunction with tabs.
I didn't talk a lot about the tabs, but we actually have talked about them a lot in past years and there are videos from previous WWDCs going into detail about how you can use those.
One of the things you can do is give a name to a tab, and then when a certain trigger occurs, you can cause that tab with a certain name to be opened in a separate window or in the same window, et cetera.
This is great for combining with things like, oh there was console output, let me go to the Tab that I've named Console.
So, if you like working in the tab format with a tab workflow, that's a great way to set it up.
You could also create your own custom actions, your custom triggers and associate a key equivalent with those.
So then, obviously that triggers whenever you hit that key combination.
And that's very useful not only for invoking the built-in behaviors that Xcode has, but also for invoking custom behaviors.
You can choose any shell script that you want to have run and associate that with any action including the Command key.
So, the script can get past certain information about the context like the file you're looking at.
So, this can be a great way to invoke custom scripts, really those power users you want to do custom operations when you hit ceratin keys.
And so, with that, that was a quick view of the UI.
I'd like to hand it back to Rick who's going to talk about some of the underlying concept of Xcode.
Rick Ballard: Thanks, Anders.
So, that's an introduction to Xcode user interface.
Let's talk about the underlying conceptual model in Xcode that you want to know about to get things done day to day.
After this section, you should come away with a few important takeaways.
You should understand how set up your own workspace with projects and targets, how to configure your settings to produce the products that you want to produce, how to use schemes to perform actions on those products like running in the debugger, testing your unit tests, profiling for performance, statically analyzing your source code, and archiving your product for distribution.
And you should come away with the better understanding of Xcode's underlying conceptual model which will help you feel like you know what you're doing in Xcode.
So, the fundamental concepts we're going to go over today are workspaces, projects and the build configurations they contain, targets and the build settings and build phases that they contain, schemes, and finally run destinations.
Let's get started with workspaces.
Workspaces are collections of files and projects with state.
So, a workspace contains a set of related Xcode projects that you want to work with at the same time, along with any other related files that you want to have like todos and notes that go along with it.
Your workspace provides repository for state.
So that means things like the user interface state.
What windows and tabs did you have opened and what files are they showing?
It means what breakpoints do you have set and other related state, all get saved per workspace.
Your workspace also provides a unique location for your build products.
So, all the build products produced by targets and projects in one workspace will go to that workspace's unique location and won't get mixed up with the build products from another workspace.
Finally, your workspace provides a symbol index of all the symbols in that workspace.
So, anything, any method, any class, any symbols you have, in any projects in that workspace, you can get to easily from anywhere else in the workspace with our features like open quickly.
So, when should you actually create your own explicit workspace document?
Well, anytime you have a set of Xcode projects that you use together, it generally makes sense to create a workspace document, put those projects in the document and work with that workspace when you're working with them.
Another important reason to think about workspaces is what we call implicit dependencies.
So, you can make targets explicitly depend on each other, but you don't actually have to do that.
If you have an application and it links against the library and you put the project that builds the application in the same workspace with the project that builds the library, Xcode will notice that implicit dependency and make that happen so that whenever you build the application target, it will build the library target first automatically so the application can link against the built library.
So, you can use workspaces to put things in together when you want to detect those implicit dependencies.
The last thing to know about workspaces is in Xcode, even if you haven't created an explicit workspace document, you always have a workspace.
Xcode projects, like if you open a bare Xcode project, it will act as its own implicit workspace and provide a unique location for build products, saved state, and so forth.
So, anything I say about workspaces applies to working with bare Xcode projects as well.
So, let's talk about projects.
Your Xcode projects are collection of files, targets, schemes, and build configurations.
So, a project contains file references to source files and resource files that you want to use, a set of targets which process those files in order to produce your build products, a set of schemes which will tell those targets to build their products and then perform actions on the product of these targets, and a set of build configurations which allow you to vary your build settings.
So, build configurations are build setting variants.
All your settings normally have a value, but when you have build configurations you can vary their value across those configurations.
So, by default out of the box, we give you debug and release build configurations and that's all most of you will need.
You generally just have two modes, I'm, you know, working in the debugger or I'm going to release my app.
Most settings don't actually need to vary it all.
You generally just need one value.
But there's some that you do like your optimization level.
When you're debugging your code, you don't want your code to be optimized.
When you're releasing to the App store you definitely do.
So, that's when you use build configurations.
Finally, you can create your own build configurations if you need to vary your build settings for another purpose.
But, most of you are probably going to be just fine with just debug and release.
You can get your build configurations and your other project settings in the project editor.
You first select the project in the project navigator on the left.
And then from the project editor pop-up, you make sure that the project is selected.
This gives you the project editor on the right which has some common project settings and this is where you define your build configurations.
Let's talk about targets.
Targets are the instructions for building one build product.
So, your targets can will reference some or all of the all source files and resource files in that target's project.
And the target contains a set of build phases.
The build phases are the high level sequence of steps that the target is going to take when it produces your build product.
There's also a set of build rules that determine how the compile sources build phase will compile your sources.
You notice a build rules tab in the target editor, but most of you don't need to mess with this.
And finally, a set of build settings will define pretty much every aspect of how that build process works.
Targets can also depend on one or more other targets and a target you depend on will be built first automatically whenever your target is built.
So, let's talk about target build phases.
Build phases again are the high level sequence of steps that your target will take when producing a product.
So, some of the common reasons why you might want to go edit the build phases are you might want to set per file compiler build settings.
You might want to add resources to your product or configure exactly where inside your product those resources go.
You might want to make a target depend on another target.
You might want run a script while building in order to do just about anything else that isn't covered by the built-in behavior.
You get at your build phases in the target editor.
So, from the project editor pop-up, make sure that your target is selected that you want to edit, and you get the target editor on the right.
And this In the general tab, we'll show some of the common target settings you might want to get at.
If you select the build phases tab, we'll show you the high level sequence of steps that your target is going to take when building your product.
So, let's go through this briefly.
The Target Dependencies phase lists all the targets that your target depends on and you can add and remove them here.
The Compile Sources phase shows all the source files that your target is going to compile.
If you want to set per file compiler flags like maybe you want to turn off ARC for just one of your files, you can do that on the Compile Sources phase.
The Link Binaries with Libraries phase lets you setup what libraries and frameworks your target's product is going to link against.
If your target produces a framework on OS X, you can control which headers get copied into that framework with the Copy Headers build phase.
If your target produces any sort of bundle type output like an application bundle, you can copy resources in to your bundle with the Copy Resources phase and by default this will copy your resources into the resource's subdirectory of the bundle.
But if you want to copy files anywhere else into your product, you can setup custom copy file phases as well.
This allows you to specify where you want the file to be copied.
And for example, here I've got a helper tool and I'm copying it into the executables directory of my bundle so that my application can launch its helper tool whenever it needs.
Finally, anything else you want to do as part of the build process, you can do with shell scripts with the run script build phase.
They can be created and dragged to reorder them.
We'll provide the build settings for the target in the environment of your scripts so it can do things like find where your target's product has been placed and manipulate it.
Let's talk about build settings now.
Build settings are the set of values that control exactly how your product is built.
So, some common reasons to want to go change your build settings are you might want to rename your product, it's time to ship and you're renaming your application.
There's a build setting for that.
You might want to set what SDK you're targeting or change the preprocessor defines that the compiler passes to outsource files when it compiles.
You might want to update your warning flags to configure just what warnings you get, and there are many, many more reasons to go in to the build settings.
So, let's take a look.
If you select the build settings tab from the target editor, you'll see the list of all the build settings available.
There's a basic tab you can select to just see the most common ones, but here I'm showing you all build settings, and they're categorized as well.
You notice that most of these build settings only have a single value that's because they don't need to vary.
But, there are some like optimization level, that vary across build configurations.
So, there's a different value for debug versus release.
There's actually another axis on which you can vary your build settings, that you can make your build settings have different values per architecture or per SDK.
And to do that, you just hover the mouse over one of these rows and a little plus button will appear allowing you to vary your build settings along another access.
So, this is the build settings that are set in the target.
There's actually an inheritance flow of build settings however.
If you select the levels tab at the top, it will show that to you.
So, the project also has a build settings tab, even if the project doesn't directly produce anything, any build settings you set on the project will be inherited by all targets in that project.
So, it provides a good way to set uniform values across multiple targets.
In the levels mode, we'll show you that inheritance.
On the right, you'll see the default value for every build setting that would be used if you didn't customize it.
To the left of that are all the build settings that are set in the project.
So, these will be inherited by all targets in that project.
Next come, the build setting values that you've set specifically in this one target, and those will override the project build settings.
You'll also notice that there are green boxes drawn around some of these cells.
We draw a green box to show you exactly where the final value from each build setting is being taken from.
So, you can see that at a glance.
Finally, on the far left, you see the result value for every build setting that will actually get used when you build.
All right, let's talk about schemes.
Schemes are the instructions for building a set of targets to produce a product and then performing an action on that product.
We support scheme actions for running on the debugger, profiling for performance, testing your unit tests, statically analyzing your source code, and archiving your product for distribution to the App store or to just save a freeze-dried copy of your product.
For each of those actions the scheme allows you to specify the set of targets that you want to build when you're performing that action, and the build configuration that this target should build with from when you're going to perform that action.
To get at your schemes you're going to go to the upper left-hand corner of the workspace window to the scheme pop-up.
If you just close this, you'll see a list of the schemes available to you in your workspace.
And you can choose to edit scheme here to bring up the scheme pop-up on the currently selected scheme.
The scheme pop-up is where you go to edit all the settings for that scheme.
To perform a scheme action, you can use the run button in the upper left-hand corner of the workspace window or the product menu which offers all of them.
So, here you can see there's a run, test, profile, analyze, and archive command.
There are also subcommands for building for specific actions without actually performing that action, and for performing an action without building if you want to just use your last built copy that you built for that action.
So, that's what your schemes are.
Let's talk about where they come from.
Out of the box, we will automatically try to create the schemes we think you want and so that means the first time you open a project or workspace or whenever you create a new project that has targets or a new target, we'll create a scheme for every target that we see so that you have at least one scheme that will build every target.
Now, I said every target, that's not quite true if you have unit test bundle targets.
Instead of putting those tests in their own scheme, we'll try to put them in the scheme of the product they go with.
So, if your tests test an application, in that application scheme's test action we'll add the test bundle target.
Likewise, if you create new test bundles, you probably don't want separate schemes for them, you can delete that scheme if we create it and instead add your test bundle to the test action of whatever it is it tests.
These schemes that we create automatically for you are per user.
So, every user will get their own copy of these schemes.
Finally, you should feel free to delete any of the schemes that we create that you don't want, because you can manually create them again anytime you want later from the scheme management sheet.
And you might also find that you want to create new schemes to support custom workflows with run script scheme actions, and I'll talk about that in a moment.
Let's talk about why you might want to go to the scheme editing sheet to actually change settings.
So, first of all, you might want to change the build configuration that's being used to build your targets when performing one of your actions.
You might want to change which unit tests get run when you perform the test action and you can also perform your tests in the test navigator one by one or as a suite or a bundle if you want now.
But, when you want to configure which tests get run standard every time you test your scheme, you do that on the test action.
You can also set arguments and environment variables that get passed to your App when it's running in the debugger or being profiled or get passed to your unit test, and that's done in the scheme editor as well.
We support a bunch of diagnostics.
There's a bunch of checkboxes in the run action that allows you to easily turn on things like malloc stack logging or zombies without having to remember the underlying environment variable that controls it.
And there are many other options that you'll see when you go to the scheme editing sheet.
We also have a more detailed walkthrough of them in last year's presentation on understanding schemes.
So, if you bring up the scheme editing sheet, you'll see that on the left we have a row for each of the scheme actions we support.
And there's also a row for the build action or for building.
Building is not actually an action.
Building is a step that happens before each of the other scheme actions.
So, when you perform an action usually you build the prod or the targets for that action and then perform that action.
You'll also see there's a row of checkboxes here, these determines which targets gets built for which action.
And this is notable in particular for the test action.
There's no reason to build your unit test if you're not going to test.
So, the test bundle, test bundle is only built for the test action by default and you can configure this further.
Also I mentioned, you notice some of these checkboxes are disabled that means that that target is explicitly being used by that action.
So, if you wanted to uncheck this target you'd have to go tell the action not to use its product anymore.
You'll notice that there's no build configuration in this in the build tab and that's because you set the build configuration per scheme action.
So, if you select another action like test, you'll see that each action has a build configuration pop-up.
So, for most scheme actions you usually want to use the debug build configuration.
Say, when you're running on a debugger or performing your unit test, but when you're archiving for distribution, you want to use the release build configuration and so we set that up by default to do that for you.
We also support additional scheme action as I alluded to before.
If you disclose the disclosure arrow to the left of any of these actions or before the build step, you can set pre-imposed actions.
It will run before or after that action or before or after the build.
We support send e-mail as one of these actions, but more usefully there's a run script action.
So, you can set up custom schemes to run any script you want to support your custom workflows.
This is especially useful with our continuous integration features.
You can for example have a post-archive script which copies your built archive to some shared servers.
So, everytime the bot produces an archive, you put it somewhere where everyone can get at it easily.
The archive action provides some things in the environment to your script to tell it where to find that product and you can additionally set a target to provide its build settings in the environment to your script.
The last thing I want to mention here is, why you would use this versus a run script build phase in a target?
Well, if your script is an integral part of producing the products of the target, that probably belongs as a run script build phase in the target.
So, no matter which scheme is building that target that script gets run and the product gets produced correctly.
If on the other hand your script is part of a custom workflow, that probably belongs in the scheme.
So that you can have different schemes with different custom workflows or have a scheme that doesn't run it when you don't want to.
So, that's how to edit your schemes.
Let's talk about how to manage them.
In the scheme pop-up in the upper left, there's a Manage Schemes option and if you choose this, it will bring up the scheme management sheet giving you all the schemes in your workspace and projects and a list of settings you can change.
So, let's talk about these.
First of all, there's a shared checkbox for each of these schemes.
Now, I said before that every scheme we give you is per user, just for you, but sometimes you might have authored the perfect scheme.
It's got just the targets that you want to build and the right arguments and environment variables being passed when you run in the debugger, and you want to share this with your coworkers 'cause everybody wants to use this.
So, if you click the shared checkbox here that scheme will actually be moved to a shared location within the project or workspace bundle, and everybody else who works with that project or workspace will get a copy of that scheme too.
This also means that any edits that anyone makes that scheme will be shared with everybody, because it's a one shared copy of the scheme.
You know, some times if you work on a big team and have a lot of shared schemes, you might have some that you don't care about and don't want cluttering up your scheme pop-up.
For example the QA team might have some special schemes that they use for custom workflows, but you don't always want to be wading through those when you're working.
So, we have a show checkbox on the left and if you uncheck this, that scheme just won't show up for you in the scheme pop-up anymore, but that won't affect anybody else.
Anybody who's sharing that scheme will still be able to use it and this checkbox is per user.
Let's talk a little bit about where these schemes actually are stored.
Actually before that, when you have a shared scheme, you may sometimes want to make some temporary one-off changes like you want to enable a diagnostic or add an additional command line argument.
But if you do that to a shared scheme it will show up for everybody and that's not always what you want.
So, in that case we generally recommend that you create a duplicate of that scheme that shared scheme, with the Duplicate command, and make your modifications in your own per-user copy of that scheme.
When you're done with that per-user copy, you can delete it to go go back to using the shared scheme.
So, now let's talk about where exactly these schemes are stored.
Every scheme is actually stored in its own separate file so that you can manage it easily in source control.
And that scheme file is stored inside a project or workspace wrapper.
So, that container column here shows you which project or workspace wrapper each scheme file is stored in.
And you can bring up a menu here to change where you want to store that scheme.
This is important to think about when you're working with source control.
So, under source control, you'll see inside a project or workspace wrapper, there's a separate shared data section and user data section for the data that's shared between all users or the data that's per user to you.
In the shared data section, you'll see any schemes that you've chosen to share, and so generally you want to commit this to source control so that anybody else in your team who checks out your project or workspace will actually get a copy of that shared scheme.
In the per-user section, you see all your own personal schemes, as well as the scheme management property list that records which schemes you've chosen to show and hide and what order you want them to show up in, in the scheme pop-up since you can drag to reorder them in the scheme management sheet.
You might often want to check in your own schemes here as well just so you can track changes and have those personal schemes available to you if you set up any custom settings, whenever you check out that project or workspace somewhere else.
There's one more thing I want to talk about today and that's run destinations.
Run destinations are the devices on which you can perform scheme actions.
So, the run destinations we give you are all the devices that you want to build for and run on, and we let you choose among all plugged in iOS devices which are configured for development, all available simulators, and the local Mac.
But of course we'll only give you choices of those run destinations which are compatible with the targets in your schemes, Deployment Target setting, and Base SDK setting.
You can get at the run destinations in the upper left-hand corner of the workspace window, just to right of the scheme pop-up.
And if you disclose the run destination pop-up you'll see all the destinations that are available to run on, again, those that are compatible with your Deployment Target and Base SDK.
Here, I have a couple iOS devices and several simulators.
If you, through the download PrefPane in Xcode, choose to install older simulators like you install the iOS 6 simulator, we'll give you those choices as well as long as your target is compatible.
So, you'd also say, you have to have your target deployment target set to 6.0, and with that simulator installed now we give you choice of which OS you want to simulate when you're choosing your run destination.
So that about wraps it up for the fundamental concepts.
We've talked about workspaces, projects, targets, schemes, and run destinations.
After today's talk, I hope you have a few useful takeaways.
You should feel comfortable navigating and editing efficiently in Xcode.
You should know how to integrate your own documentation in Xcode's help and code completion using the doxygen format.
You should understand how to customize Xcode's behavior, so the UI behaves just the way you want.
You should know how to create and configure your own workspaces, projects, and targets and set their settings appropriately.
And you should understand how to manage and share your schemes with your teammates.
If you have more questions I highly encourage you to contact Dave Delong who's our App Frameworks and Developer Tools Evangelist.
We also have documentation on Xcode at developer.apple.com/xcode as your jumping off point.
And if you haven't used it already the Apple dev forums are great place to come and discuss and ask question about the new versions of Xcode or existing features.
That's at devforums.apple.com.
We have some more sessions about Xcode coming up for you today.
I encourage you to take a look at these and go to any that strike your fancy.
We've got a lot of great information for you.
[ Silence ]