iPhone • 1:09:46
The Xcode project system scales from building the simplest Mac and iPhone applications to the most complex. Get a complete overview of the system, including how to create custom build configurations, support unit tests, use compiler settings to track down coding errors, build 32- and 64-bit universal applications, and use SDK settings to ensure compatibility for your target customers.
Speakers: Chris Espinosa, Rick Ballard, Brent Shank
Unlisted on Apple Developer site
Downloads from Apple
Transcript
This transcript has potential transcription errors. We are working on an improved version.
Good morning, everybody. Welcome to session 424, The Introduction to Cocoa and Cocoa Touch Development with Xcode. My name is Chris Espinosa. I'm the head of the Xcode Core Team. We got a pretty packed agenda for you today, so we're going to jump right in to it. This is an introductory beginner session to the Apple developer tools, and it applies equally to those of you developing for the iPhone as for the Mac OS.
You're going to see a lot of redundancy here, a lot of repetition from things you saw yesterday in the developer tools keynote if you were there, and this morning, if you were in the introduction to iPhone development. But we're going to go a little more in-depth to the concepts and practices of developing with Xcode.
Instead of rushing by things, we're going to go a little deeper into the build system, into creating new projects, and then to debugging. We're going to walk you through the whole basic development process, and we're going to set you up to making the most of the rest of your week.
Now the big picture is that development for software is a cycle. First thing you need to do is design-- really helps to start out with an idea of what you're trying to do, rather than jumping in and just writing code. Xcode doesn't help you much with that, but the next step is starting a project and then editing your code-- going to cover a lot of that. Then you build your code and create something that you can run. But before you run it, you need to test it. We're going to talk about the different ways that Xcode helps you test your code even before you start executing it.
Then you execute and debug it, then once it's debugged and working, then you get to tune it. Other sessions cover tuning, we're not going to talk about that very much today. Then you package it and deliver it to your customers. Those are also covered in different sessions because they're different from Mac OS X and iPhone. We're going to cover the things in common from edit through debug.
Now first, you got to get the Xcode tools on to your Macintosh, and yes, you need a Macintosh in order to develop for the Mac OS X or iPhone. The easiest way to get them is when you buy a new Macintosh, the Xcode tools are on your Mac OS X installation DVD, and you can just install them from there.
But we're constantly updating the tools, and so the newer tools are almost always available online. You sign up for the Apple developer program, and you can download them-- either just the straight Xcode tools to develop for Mac OS X, or you download the iPhone SDK from the iPhone Dev Center.
In most cases, when you download the iPhone SDK, that includes all the Xcode tools you need, you don't need a separate download. And if you have already downloaded the proper version of Xcode, you can usually just get the iPhone SDK as an add-on for that. So you never have to download Xcode twice even if you're developing from both Mac OS X and for the iPhone.
When you install them, you get a new folder at the top level of your hard disk called the developer folder. This is the center of your developer experiences where you're going to be spending all of your time. Now you open it up, and there's a lot of things in there, but the only thing that you particularly care about especially as a beginner is the applications folder inside the developer folder.
Let's take a look at that. Xcode is the integrated development environment. It's where you start new projects, it's where you edit projects, it's where you launch projects, it's where you debug projects. If you're developing iPhone applications, it's where you install and configure software on your iPhone. It's where you'll be spending most of your time. Interface Builder is where you design graphic user interfaces for the Mac OS X and the iPhone.
It's where you're going to be spending most of the remainder of your time. If you're a Mac OS X developer, you may use Quartz Composer to develop animations and graphics for your application. You're going to be using Instruments to fine tune. That will be covered in sessions later in the week. There are some utilities, graphics tools, and other performance tools that you'll use when you're more advanced on the platform. For this, we're only going to cover Xcode, and we'll dabble a little bit into Interface Builder.
Now, the developer folder is something you're going to hear a lot. Well in fact, you can have multiple developer folders. Like I said, we update Xcode tools over time, and we have this practice of releasing betas of new tools, and we don't recommend that you use a beta toolset to develop production code. This leaves you with a dilemma.
What if I want to ship something today, but I'm using the beta toolset in order to experiment with APIs or new operating systems? Well, you can install 2 developer folders side by side, and which Xcode you launch from which developer folder determines what sets of compilers, what Interface Builder, what all other auxiliary programs you get.
So you can have a standard developer folder that's a production version on your machine. And then if you want to install a beta of a future developer version for a future SDK, you can install that side by side, and then alternate between one and another. So you have the best of both worlds. You can develop production code with a production environment with production compilers, or you can use our experimental stuff for developing for a new OS. Now let's start with working with Xcode.
The basic unit of Xcode you'll be working with is the Xcode Project. Now project is the container that holds all of the stuff you need to develop. First thing is your source code files. You're going to be writing source code in text files, storing them on disk, and accessing them through the project file. There are also user interface files. They are usually called .xib or .nib or XIB or NIB files.
You'll be editing those in Interface Builder. The third is a structure called a target. A target is a set of rules and instructions for how to build a piece of software, an application, a library, something like that. The target is probably where you're going to be spending most of your time doing project configuration, setting up settings and fine tuning things.
And finally, there's the project file itself. A project can hold a lot of other things than just resources in your interface files. You can configure your project to hold documentation, additional information, you set up your project for source code management, you share your project with other people; your project holds information about your screen layout in certain preferences.
So each of these elements of your project has function. Now the project file-- we call it a project file, but it's actually a directory. It has a lot of files inside that you'll never-- or rarely see, it is a directory. But there's a lot of stuff that's stored in it and is stored in a .pdx proj file inside that project wrapper.
The main thing is that the project holds references to all of the source code that is in your project folder. It has groups; yellow folders that organize those. So you can organize those arbitrarily. So no matter how your source code is laid out on disk, you can organize it logically and conceptually inside the project window using the yellow folders called Groups.
It's got targets which are the organizing principles for building build products, and we're going to use the term build product a lot. A build product is what you're trying to create-- an application, a library, something like that. It has executables. Executables are how you launch your build product, launch it as a Macintosh application, launch it in the iPhone simulator, launch it on an iPhone device. And executable is instructions for how to run software.
And then finally, all of your user settings, your bookmarks and history for going back and forth and finding stuff in your project, the window layout, if you like big windows, small windows, tall windows, narrow windows. The last way you had your project set up, that is stored on a per user basis. So if you share a project with other people, your settings are yours, their settings are theirs. Breakpoints for debugging, when you set a breakpoint, other developers will not hit that breakpoint for you.
That's very convenient if you're working in a group setting, and then other user specific configuration. Now, people will always say you're working with an Xcode project, but the most crucial thing to remember is that the vast majority of the time you're working in Xcode, you're focused on a single target.
A target again is a set of instructions for building one build product. One target, one build product, remember that. A target references some, maybe all the files in the project. But if you have multiple targets in your project, they can reference different sets or source files. A target contains build phases. Build phases are the steps that Xcode goes through that turn your source into a product, and build rules determine how Xcode does that, how it compiles source files, how it processes NIB files.
And then for each build phase, a set of build settings applies to that phase. These are parameters that change the way that that build phase works. So when we go into the demo, you're going to see how you use build settings to affect how code is built.
And so, you can have a debug configuration which is all of your settings for building code for debugging, then your release configuration is all your build settings for building code for production. Now, targets, you can have multiple targets to build different things, and you can also have these things called aggregate targets that build other targets.
So if you have a series of iPhone applications, or if you have a Mac application that has both the main application and then an auxiliary application, or a shared library that is used in multiple applications, you can have multiple targets in one project, and then an overall aggregate target that simply builds them all in sequence.
So, now it's time for our first demo, I'd like to bring Rick Ballard up from the Xcode team to show you the basics of how to start with building an Xcode project. Rick?
[ Applause ]
Thank you. Thanks, Chris. I'm going to take you through creating a new project and then briefly step through looking at each of the things that Chris just talked about in Xcode.
[ Pause ]
Great. Sorry about that. So, we're going to start out by finding Xcode at the root of our disk here.
[ Pause ]
Xcode's welcome screen provides you a convenient jumping off point to get started, either by creating your first new project or further new projects, diving in to the tutorials and sample code that we provide, or exploring resources that we have on developer.apple.com. On the right hand side, you notice that we provide a list of the recent projects that you've been working with This makes it easy when you launch Xcode to jump right back in to what you were working on last. If you ever close this window and want to get back to it, you can find the Welcome to Xcode screen in Xcode's Help menu, but all of the functionality here is also available in Xcode's menus such as new project, or finding your recent projects.
We're going to start out here by creating a new project, and this brings up the new project assistant. Xcode's new project assistant provides a wealth of different types of projects to get you started quickly no matter what you want to build. The first decision that you make in a new project assistant is the overall type of product that you're going to build.
Now, none of the decisions that you make here are irrevocable. If you change your mind about what you're building later, you can edit your project, edit your settings, add new targets, to make whatever you want to make. But by making the appropriate decision now, you let us start you off with the right kind of target, the most appropriate build settings, and some sample code to help make it easy to get started quickly.
On the Mac OS X side, you'll see that we provide several different types of applications, different types of frameworks and libraries, and a number of different types of plug-ins, both for applications and kernel extensions for the system, and things like that. On the iPhone side, all applications use Cocoa Touch, but we give you a choice about the category of application that you're going to create, allowing us to start you off with some appropriate sample code.
The icon also supports a static library type. So if you want to share code among multiple iPhone projects, you can use this to build into a static library, it gets built into every iPhone application that wants to use it. You notice when you select a template, that we provided a few options such as whether or not you want to start using Core Data, or a document-based architecture.
Again, none of these decisions are irrevocable. But we'll start you out with a project already set up to use these options if you want. We're going to start out today by creating a very simple utility application for the iPhone, and I can choose where to put it and what to name it.
So I'm going to call this "next big thing". Don't worry too much about what you want to name it now, because we now make it really easy to rename not just your project, but the target that's associated with it, build settings that go off it, and any other interface-related functionality that might use the name that you've chosen here.
So now we've got a project window up, and you can see in the left hand side, I've got the structure of the project that Chris described to you, and in the right hand side, I've got a detailed view of what I've got selected. I can flip through here and take a look at my source files, which I'll automatically open up in the embedded editor when I select them, or which I can double-click to open up in a separate editor if I prefer to work that way.
I've got resource files, in this case, this iPhone template comes with 3 different XIB files that comes to my interface. To edit these, I could go launch Interface Builder or just double-click in here, and it will bring up Interface Builder for me. And you'll see, this is part of my interface, the objects of my interface, and the interface for adding new objects to it and so forth.
I've also got some references to frameworks in this project. These files here, like UIKit.framework is a reference to UIKit on my disk, because my project happens to use that and a couple other frameworks to build. In the targets group, you can see that this project came with one target, "the next big thing" target.
That target produces the product that I'm going to run here. And I can just close it to take a look at the different build phases and their contents. Like here is the phase where the target compiles the source files, and you can see that it's got 6 different source files that it's going to compile in this phase.
Each of these objects here, whether a target or a project or even my file references also have some additional settings you can drill down into by clicking the Get Info button in the toolbar or using Get Info in the File menu. You see that I have executables here, this is where we store settings that you want to use when running, like arguments and environment variables to the launch, and there are a couple of other useful groups down here. Like if I'm setup to use source control, I'll have my source control status available. Or I've got some smart groups which I can modify or define myself in order to filter down to a specific set of files that I might want to look at frequently.
Finally, you'll notice that the last yellow group up here is my products group. This contains references to all the products built by all the targets in my project. So you'll notice that there's a reference to "the next big thing" application which is what this target builds. It's in red because the file doesn't exist on disk yet, and it's telling me that.
Why doesn't it exist? Well, I haven't built it yet. So at this point, I'm going to go ahead and build and run this project, and in the status bar, it will show me my build status zip by quickly, and then launch this application in the simulator. And you see, I've got my application up and running here, and the file reference is now black, showing me that it does exist on disk. If I want, I can ask Xcode to actually show me what it just built by right-clicking on it.
Well, there's a Reveal in Finder command which-- here we go, I used a different keyboard mapping. I can Reveal in Finder and see the application that I just built, and it's DCIM, which really iPhone developers is very useful to hang on to. And I've just got a project that I built. This is how easy it is to get started in Xcode, and get up and running quickly. Let's dive in a bit deeper now into how you actually go about building your project and how the build works.
Chris?
Now, we'll come back to building and editing the project itself in a little while, but we're going to spend some time on editing the source code because even though it's 2009, we as programmers still write most of our applications by typing characters into a text editor. And I know that text editing is a deeply personal issue with very, very many programmers, sometimes weirdly so. And while Xcode-- we've set up the defaults for the text editing behavior to be a great experience for most people.
Everybody has their personal preferences, and Xcode is highly configurable to adapt to the way you like to work with program text. We have syntax coloring, so you can choose whether you like black on white text, white on black text, bold colors to distinguish the different syntactic parts of your program or muted colors.
You can choose different syntax colorings according to your own working style or create your own syntax coloring, use different fonts and sizes and even styles. I happen to like my comments in swishy italics because it gives that certain je ne sais quoi to my source code. [Laughter] Indentation is a big issue.
Sometimes you have to use an indentation style that fits in with your group, sometimes you prefer to have 4 spaces or 8 spaces. Xcode has a very flexible indentation system, you can use spaces or tabs or a combination of both, and you can reinvent texts semantically on the fly.
Some people think wrapping is a complete anathema, some people think wrapping is a fundamental part of the editing experience.
You can have either or both if you like on a file by file basis. Some people like to see the majority of their editor showing nothing but text, some people like to see line numbers and even column positions in order to get a numerical guide. They remember things by line number.
You can see the line numbers in the gutter. You can see the column position in the navigation bar at the top of your text editor. All of these are very easily controllable in the View menu in Xcode. We have another feature that is rarely seen in other editors. It's called Code Focus.
Xcode knows semantically the nesting level of your code even if the indentation is incorrect. We've got a very handy feature called Code Focus that shows you in a highlighted form, it gradually dims back things that are further and further out of scope. So if you have-- and this is especially helpful if you have a long switch statement with a lot of cases and you happen to have forgotten the closing brace or a colon somewhere-- you can very easily see the compilerized view of your program and see that the indentation doesn't happen to match the syntax, and where your case may be following through when you didn't intend it to.
You can even have that follow you as you type so it only highlights the thing that you're working on right now. Now the second part of working with the editor is not just looking at your text, but it's navigating around the different source files, and Xcode has a number of different ways to move you from one place in the code to another place in the code and back very rapidly. The navigation bar is the key thing we will be using.
You can use it to move from file to file, you can use it to move back and forward and when you're editing position in the current file as well as across multiple files, and you can use the function pop-up right in the middle up there with the blue M to navigate to any function or method in your code very-- in your current file very quickly.
Also, a number of other controls on the far right side navigate up and down the class hierarchy of the current class, jump directly to the header file for this source file, or jump to any header file that this source file includes directly with the pop-ups on the right side of the navigation bar.
There's a command called Open Quickly which is incredibly useful. You can use it to directly jump to any file or symbol in your project or in anything that the header files include. Just type command-shift-d brings up the Open Quickly box, type the prefix string of what you're looking for, press return, you're there instantly.
If you're looking at a symbol in source file and you want to know where it's defined, you Command-double-click that symbol and it jumps directly there and shows you what it is, then you can hit the back arrow and go back to where you were. There's also a pretty functional class browser which shows you the entire class hierarchy of your application and all of the frameworks that it includes so that you can navigate up and down class hierarchies.
Finally, entering text is laborious, especially with all of the long variable names that Xcode view-- that the Cocoa and Cocoa Touch Frameworks use, capitalization which is crucial in the name of Xcode itself as well as in the rest of the C language. Code Sense code completion really helps you get accurate completion and also browsing of realistic and correct options as you type. You saw little of the code completion yesterday in the keynote. We're going to have a better demo of code completion coming up in just a few minutes. The most important thing is you can get that code completion from the menus but you almost never will.
Once you learn command-period for complete now-- control-period for complete now, control-comma for popping up the completion list, and control-/ to move from one placeholder to another. Once you get those memorized in your fingertips, you will never leave the keyboard to type long passages of source code and have Xcode do most of the typing for you. It's really, really fast.
Then another feature which is very useful when you're reworking code is Edit All in Scope. You select a variable name, you choose Edit All in Scope, and it will find all the instances of that variable name in the scope of the method that you're using and it will allow you to mass edit those, and that's a very easy way to rename an instance variable, rename a locale very quickly and reliably.
Xcode also supports all the normal things you'd expect to find in an IDE, Single File Find and Replace, as well as Project Wide Find and Replace that can work either on plain text, regular expressions, finding definition sites or finding the uses of-- all uses of any symbol in your project.
There are refactorings for Objective-C that allow you to rename a method globally across-- or a class or a method globally across your source code, hoist a method call up into a super class, or refactor certain methods in the class down into a sub-class. You select the identifier you want and you choose refactoring from the Refactor menu-- Refactor from Edit menu.
There will be demos on that later on this week. But most importantly, if you're beginners and if you're in the beginning session, you probably are, getting help, and finding out what you need to write is probably going to be the most useful thing to you when using Xcode. The developer documentation window is going to be the center of your existence for quite a while.
It has the complete developer documentation on all of the Cocoa and Cocoa Touch APIs, it has all of the user guides for using Xcode, and it has all the other information about Mac OS X that you need to know in order to write effective Mac OS X and iPhone applications.
If you get to this from the Help menu, there's some other useful things in the Help menu, the Xcode Help and Welcome to Xcode as Rick demonstrated, the release notes which as you move from version of Xcode to version of Xcode, you can see what's new and what's changed.
The Search window in the Help menu not only searches the Xcode documentation, but also searches all of Xcode's menu. So if you're looking for a function like, Where do I re-indent, you just type re-indent into the Search menu and it will jump you directly to the menu item that does that.
So another thing that will really be useful for you as you code, because the documentation window is big and it kind of takes up your whole screen, but we have a Quick Help window that is small, that you can use to float above your code, and it will show you a little synopsis of each function and API or method that you're using, and it will give you links directly to the documentation for that if you want to read further, or the header file in which it's defined.
If you want to see relatives of it or what else is going on or see other things. Also it has links directly to sample code that shows how that API is used. Quick Help is extremely useful while you're coding, just to see what's going on to learn more about the APIs you're using. So now, I'd like to bring up Brent Shank from our Developer Tools Documentation Group to take you through the basics of text editing and using documentation in Xcode.
Great. So to do that, we can launch Xcode, and I'm going to choose developer documentation from the Help menu, this will get me to the documentation window. And I'm going to search for an interesting sample code project, something that uses an NSBezier path, so we draw something pretty and maybe an affine transform. So you can see how fast it is to search all of the Apple documentation.
You get instant results back. All right, so I see a lot of results here, let's choose squiggles, that's one of my favorite sample code projects, and all you need to do to get this going in Xcode is click the zip file link. Xcode asks you where you want to put it on your system, you click Choose, and Xcode opens it up for you. Let's build a run and see what this does. So that built really fast. I'll maximize the window there.
And as I click the mouse and move around, I can draw pretty lines, and as I move the slider down here, they get rotated around the center of the view and multiply, which is pretty cool. Well, to learn a little bit about Cocoa, I want to modify this sample and in addition to drawing the lines, I want to draw some text.
So we have to learn a few things. First thing we have to learn is how this application is doing its drawing. Well, to figure that out, let's do a project-wide find. We're going to press command-shift-f to bring up the project find panel, and I'm going to look for-- search for the word draw.
Hopefully that will lead me to the right place, but I want to search everything in the project. OK, so as you can see, we have a lot of hits here, some things in comments and in the read-me. I want to narrow down my search and just look for APIs that are defined in my project. So I can do that by selecting the definition search from this menu on Quick Find. And here it is, I have one method, the instance method called drawRect. That looks like a good place to start.
So notice you can view this first file edit right from the embedded editor in the project find window, or if you're like me and you prefer to have a separate editor window, all you need to do is double-click the result and that will open up from the separate editor. So, as Chris said, text editing is a very personal thing.
So let's get personal for a minute. Let's go to Xcode's preferences and let's check out the fonts and colors preference. This is where you can set all your preferences for the font that is used in the editor, the colors that we used for syntax coloring, the size of the font and everything.
I'm using the presentation font right now, so everyone in the room can see it. But Xcode comes with a number of pre-built themes that you can use. You can create your own themes. You can copy any of these default themes and customize it just the way you want. And let's switch back to the presentation theme. If I'd select the text editing preference, this lets you customize the controls that are shown in the editor. I'm going to turn a few things on here.
I really like to see line numbers and column position, and for some reason, I really like the page guide. Then we click Apply and get a preview of that, and you can see in the text editor, I now see line numbers and the page guide. So when you first are getting to know Xcode, take a while, launch the preferences, check them out, you can customize the editor just about any way you want to. So, let's go back to the source file here. One of my favorite features of the text editor is the ability to temporarily get rid of code or parts of this source file that I'm not concerned about at the moment.
So for example in this case is this long copyright statement. If you move the mouse over to the code folding ribbon next to the line number column, all I need to do is click it and it temporarily goes away, and that's persisted if you close this file and reopen it, and even if you quit Xcode. So it's a great way to focus in on just the task at hand and in this case, it's learning what this drawRect method is doing. To please the demo gods, I'm going to open that up again. So let's see what drawRect is dong.
It's a drawing gradient that's set up earlier in a class. It's using this NSAffineTransform to rotate the view, and then a couple of 4 loops here are responsible for drawing each of the squiggles. So I think I can intervene here, add some code and in addition to drawing the lines, draw some text. First thing I need to do is learn how to layout text.
Well, let's go back to the documentation window, figure out how to do that, laying out text. I can type. That sounds like a good phrase. Sometimes when you're searching for phrases in the documentation window, it helps to change the match type to an exact match. So when I do that, first result, laying out text along an arbitrary path, that looks like exactly what I was looking for.
So this is a great article in the text layout programming guide. It tells me that if I set up the Cocoa Text System, I can get this layout manager object. And once I have a layout manager, I can draw a text anywhere. So this is great. Let me copy some of this code over here.
This looks like a good one to copy also, and we'll also copy that one. OK, so imagine that all that code was pasted in haphazardly. So looking at the code that was pasted in here, I want to indent it to be clean. And I could go and do that manually, but I know Xcode has a function for doing that, just not sure where it is. Well as Chris said, you can use the Help menu to find menu items in Xcode. So bring up the Help menu and in the search field, we can type indent, and you can see that Xcode finds that menu item for me.
It's buried somewhere in the Edit menu. So there are lots of little things like this in Xcode. They can be hard to find especially if you're getting used to Xcode, use the search in the Help menu and you'll find all of these hidden gems. OK, let's change the string that we're actually going to draw here.
Great. So the next thing I need to do is use variable names that are kind of generic. I like to make them a little more interesting. We notice I have a bunch of instances of layout manager, and I could change them all individually, but that's kind of a pain, be really great if Xcode could help me out with that.
So to do that, I just need to select one of the variable names and you see this little menu, this little arrow pops up next to it, and I click down, I get a contextual menu. Edit All in Scope is the first item. You notice when I select that, all of the instances of that variable in this scope are selected. And as I start typing, they all update. I can press up or down arrow to accept that. I can also activate Edit All in Scope from the keyboard command-control-t.
So if you're a keyboard person, you don't have to leave the home ground to do that. And I'll press the down arrow and there we go. Xcode has a lot of powerful batch editing features like this in the editor. So the next thing I need to do is, I have this layout manager and I know it can draw a text for me, I just don't know what the name of that API is.
Well, I could go and read the class reference for the layout manager, or I could just let Xcode do it for me. So I'll start typing in a variable name and you notice as I type some characters, Xcode is suggesting what it thinks is the best possible choice for that variable.
And I just need to control-period to accept that one, and I'm going to type a few characters here, and What's Xcode doing here? Well, it's pretty smart. It knows all of the methods that are defined on NSLayout Manager. And because I've started an Objective-C message to that, it's helpfully suggesting things that I could call on that object. And as I cycle through the list here, I see a bunch of good options.
Problem is I'm not exactly sure which one of these I want. Well fortunately, Xcode can help you with that too. From the Help menu, I'm going to select Quick Help. Quick Help, as you saw yesterday in the State of the Union, is a small panel that brings the API documentation right into the source code editor. So you don't have to leave your context, you don't have to bring up the DOC window. It brings the essential information to you right in the editor.
I can continue cycling through the code completion list and you notice as I do that, Quick Help updates, it gives me an abstract, the declaration and some pointers to other documents and sample code projects that are applicable to this symbol. It even works with the code completion list.
I can press control-comma to bring that up. And as I cycle through these, it looks like I found what I'm looking for, a drag list for glyph range or point. I can hit Tab to select that, and now I need to pass in a range. Fortunately, I pasted that above. And now, for the second argument, I need to add a point.
And again, as I complete that, Quick Help helps me understand which, what kind of argument this is. So I need an NSPoint. I'm pretty sure an NSBezier path will give me that. But to be sure, I want to go back to the documentation. I can command-option-double-click on that symbol, and you notice I have a bunch of documentation sets here I installed on my system.
I'm going to switch to the Snow Leopard DOC set, and look at NSBezier path, look in the summary of the class reference here. And under the query paths task, there's a current point method, I click on that, and that will return an NSPoint which is what I need. So this is good news.
I'll go back to the code editor here and again, I'll just start typing the NSBezier path object and Xcode is saving me so many keystrokes here, this is really fabulous. So, let's build and run and see what happens. All right. Well, something is happening there but the text is kind of dark, I can't really read it.
Again, let's go back to Xcode and add a little bit more code. I want to change the font color and the size of the text that's drawn. Again, there's a lot of API in the text in Cocoa for doing this. I don't remember what it is, but I know I have this text storage object and that's just a mutable attributed string, so I can add all kinds of attributes to it. Add attribute, there's one for adding multiple attributes at a time or one at a time. So again, Xcode is being really helpful. In this case, let's add foreground color and I think each squiggle has a color.
Again, Xcode knows color property on squiggles and completes that for me, and the range I want to use. Again, I can hit Tab to go to the next code sense completion placeholder, and the range I'm going to pass in. Someone doesn't have wrapping turned on. What were you saying, Chris, about this being personal? Now, I can't get any work done.
OK, we'll do that, and I want to add one more, text storage and attribute. Let's add a font and let's add consistent font, let's make it really large, make range. I could just copy and paste that, but it's good. So fast, in completing these things, I don't need to. OK, so that looks good.
Let's build and run, see if I typed everything correctly. And now as I type-- as I move the mouse around, we're drawing text. And the coolest part is when we rotate this, we're now drawing text anyway we want to. So this is a pretty advanced Cocoa Text System task, but Xcode made it pretty easy to learn it So the combination of Quick Help and the DOC window and code completion makes it really easy and fast to get up and running with Xcode and Cocoa and Cocoa Touch APIs. Back to you, Chris.
OK. So you've seen the basics of creating a project, and you've seen the basics of editing text and getting help to figure out what you want to put in your project source files.
Now, building is the process of compiling all your sources and assembling all of the resources into an executable that Mac OS X or the iPhone OS can actually run. When you build, you have 2 choices. One is that you can use our dedicated build results window which is tuned to the task of building and getting build results and figuring out what's going on in the build, or as you saw in the keynote yesterday, you can get most of the build results right in your editor with our inline message bubbles for errors, warnings, and static analysis results.
You can even go back and forth between the two It's pretty easy to do. The build process consists of taking the list of build phases in your target, and processing every file in the build phase one by one. First, we take all of your resources, your strings, your graphics, your NIB and XIB files and copying them into where they belong in the final build product. Second is, we take all of your sources and compile them and they include their header files in order to be compiled. Now, both of these processes are fairly complex.
The compiler one even a little more so. Under the covers, what Xcode is doing is, it's actually invoking the kind of command line tools like the GCC compiler that you would see executed from the makefile at the command line. In fact, when you're looking in the Xcode build results window, you'll see a little icon over on the right edge, which if you click it, shows you exactly what's going on. This is the exact command line that if you copy and paste it into the terminal and execute it, will compile that file and create the .0 executable file that corresponds to that source file.
Xcode is a thick, not a thin, a thick veneer on top of the low level compilation tools that you're familiar with if you come from the Linux or makefile tradition, and you can see exactly what Xcode is doing under the covers by looking at the individual build transcript to that step. You can even, by using control-click in the build results window, you can get the full transcript to see the whole process of what Xcode is doing.
And then finally, Xcode links your individual object files from the individual source files with other static libraries and with the dynamic frameworks, in order to create the binary that goes into your executable that's actually ran. Now there are a couple of tasks that are very, very common in configuring your target to build properly, and you get at almost all of the things you want to do on your target by choosing Edit Active Target from the Project menu, and you see the target inspector.
In the general pane of the target inspector, the first 2 things you're going to do. First is if you have one target that depends on another, if you have an application that needs to have a static or dynamic library built first, or if you have an aggregate target where you want to say build this target and then that target and that target, you use the target dependencies panel in the general pane of the target inspector. There's a little Plus button on it, you click the Plus button and you just add other targets to it. Whenever you build that target, it will build the other targets first.
It's the basic way you set up dependencies in Xcode. The second thing is that if your source code uses a header file in the framework, you're going to need to link with that framework. Now normally, you just drag and drop the framework on to your target and that works. But if you want to browse the frameworks and see what else is available and what you need to add, or if you want to go get a static library from somewhere, you use the linked libraries and framework pane in the general inspector.
Again, you press the Plus button at the bottom, a sheet drops down and shows you all of the frameworks and libraries that are available to you. You pick one, and it goes into the list. These are some very common tasks in managing your target for what targets it depends on and what frameworks and linked libraries it depends on.
Now I mentioned earlier that build settings are the parameters that control how each build phase works. You're going to be spending a fair amount of time changing build settings in your project. Build settings are specific values that are passed to each tool as it executes each build phase.
And they're organized into configurations. The basic configuration you'll get with almost every Xcode project is a set of debug build settings, and a set of release build settings. The debug build settings build an optimized version usually for a single architecture for build speed that makes it very easy to debug and figure out what's going wrong with your code, but doesn't provide the best user experience for the end code. The release configuration is optimized, it doesn't have as much debugger information in it, the code runs a lot faster, and it's packaged for delivery.
So you pick one or the other, you can set one thing common across all configurations, like your name is probably going to be common across all configurations. And you can set things that are separate for each configuration like the optimization level. Build settings are arranged into a hierarchy. Most of the time, you'll want to work with build settings at the target level.
And you do that by going to the Project menu, Edit Active Target, and then clicking the Build tab in the target inspector. But sometimes, you may want to set a build setting that applies to all of your targets. For example, if you want one optimization level across all targets, you can set that at a higher level, at the project level. Here's the hierarchy in action.
Xcode has certain defaults for every build setting that you get, and so there are some things that are predefined by Xcode and a lot of things that are just left loose. When you create a project, some build settings are created in that project that will apply to all targets in that project unless they're overridden. You can set very common things here if you happen to like a certain style of warnings for example in the compiler. Set it at the project level, it will apply to everything in that project.
If you want to-- if you're building a certain style of code, you set it there. And then finally, on a per-target basis, you can set things that are characteristic of or specific for that target. So for example your-- the product name, what you're building should really be set at the target level. Each level inherits from the previous level and overrides it. If you know object oriented programming, this should be a very, very familiar concept. The number one user error with Xcode is-- I set this build setting and it didn't take effect.
Well, where did you set it? I don't know. They usually set it at the project level, but they have another setting at the target level that's overriding it. So always work from the bottom upward, from the target to the project level when you want to set those settings. Certain tasks you do with build settings. There are hundreds of build settings.
There are build settings for each individual warning you can get out of the compiler. There are obscure build settings for certain things you want to do with the linker. There are build settings for packaging. But really, there are only about 5 build settings that you're going to be using on a routine basis as a beginner Xcode programmer.
The first is the name of what you're building. When you create a new project, this is set by default to the name of the project. But remember, the project is not the build product. You can change the name of what you're building at any time without ever touching your project name.
You go to the target, you look for the product name build setting and you change it and that changes the name of the application you're building. It's that easy. If you're including code from the outside, you'll need to tell Xcode where to find the header files for that code. So Header Search Paths are a pretty common thing to change.
Once again, you'll usually change this at the target level, but you could change this at the project level if you have a bunch of targets that all refer to the same external library for example. If you-- when Xcode builds its intermediates and it builds its build product, it puts them in something called a build folder. By default, that build folder is located next to your project file in your project folder.
Some people want to put it on a scratch disk, some people want to put it elsewhere consolidated in one place so that multiple projects can share their results. You can set the build products path in your build settings. You'll usually do that on a project level so that all of the targets go in the same place.
The next two are really important. I'm going to be spending a little time on them. This is the API, the SDK and the API for your application. When you write code, you have to choose the model that you're writing for. You have to choose what operating system and what version of the operating system you're writing it for. You choose an SDK, a software development kit, and that has all of the APIs you're going to be coding against. It has all of the classes and all of their methods. But that doesn't lock you into running on that.
You're going to run on that operating system and all later ones of course. But also, you can make your code run on earlier versions of the operating system by setting a separate build setting called deployment target. And let me show you how those work. Deployment target in SDK lets you trade off the features your application uses against the number of users you're going to reach.
Because when Apple releases an operating system, it has certain features, and then we upgrade it and it has more features, like in iPhone OS 2.2 or in Mac OS X 10.5. And then another version comes on and it has still more features, like in iPhone OS 3.0 or Snow Leopard.
The problem is the newer OSs have fewer users. And if you lock yourself into a later OS, you're restricting yourself to a smaller number of users. You'd rather reach the larger number of users on the earlier systems even if that means that they won't get the features of the newer operating system. We have 2 controls that help you do this.
First is you set the deployment target for the earliest version of the operating system you want to run on, like Xcode-- like Mac OS X 10.5 or iPhone OS 2.2. That sets a baseline. Your code won't run earlier than that, you may cut off some customers, but it sets a baseline for your functionality and you can code with confidence against that.
But then you set the SDK for the highest version of the operating system whose features you want to use. Now, if you set them to be the same thing, if the deployment target in the base says you cater the same thing, then you're golden, that's pretty easy. You get all of the features of that operating system, and you redraw all of the customers of that operating system in later, that's pretty easy.
But if you want something that has a little more reach and some more features, you move the bases-- you move the SDK and the deployment target up. So if you want to write a Snow Leopard only application, or if you want to outride an iPhone OS 3.0 only application, you move both in tandem, OK? Now, the next thing takes work.
If you set the deployment part target back earlier, I guess this way because I'm mirrored. You get to run on earlier versions of the operating system, but you have to do a little more work. Every time you call a new feature, you have to test that feature to make sure it exists at runtime. So you set your deployment target for like iPhone OS 2.2 or Mac OS 10.5, even with your SDK at a higher level, and you get more features but you have to work to access those features.
Similarly, you can set it all the way back to say, Mac OS X 10.4, iPhone OS 2.1 or 2.0, you get the maximum number of customers, but you have to do the maximum work to make sure that every time you use one of the features in a later version of the operating system, that it's available.
These 2 controls are very important for using new features and new operating systems, and reaching the maximum customers you want. Now with all of these controls, with all of these targets and configurations, and SDKs and the multiple architectures, you have to control what you want to build at any given time. Now, when you press the Build button, you're only building one thing.
When you click the Build button, you build one thing. And in a sample demo product, it's pretty simple. You have an application. Do you have one target in your project, and there is one configuration of it, like the debug configuration. But as time goes on, you may add different targets and maybe an aggregate target to build them all.
You use the active target pop-up to control which target you're going to build. Now, that's the debug configuration. You may also have a release configuration. When you want to build your product and distribute it, you choose the release configuration. That gives you another set of options and builds another set of executables.
So you can build any target for any configuration just by picking from active target and active configuration. Now, for most of our platforms for Mac OS X, you have a choice of architectures to build for. For building debug, we generally build the architecture for the machine you're running on, just one because it's pretty easy. But you want to deploy for people who have multiple architectures. So, and if you're building for 10.5 for example, you probably want to deploy PowerPC architecture and i386 architecture, and x86-64 architecture, and you may not want to test those one by one.
So we can use the active architecture pop-up to pick along that access. So the combination of active target, active configuration, active architecture picks one of these massive grid to build at a time. And you pick which one you want to build and run at that time. Now, there's an additional control called Active SDK, and that you can use in different ways for iPhone than for Mac OS X. The Active SDK overrides the base SDK setting in your target. So if you're set up to work for the iPhone 3.0 device, that's what your code is written for, that's what the base SDK is.
But suppose you're not ready to deploy to the device yet, you just want to debug and want to debug in the simulator. You change the Active SDK to the iPhone simulator SDK and then that overrides the SDK value and lets you run in the simulator. Similarly, if you have a Leopard application, you want to build it and you want to test it with the Snow Leopard APIs just to see how it builds without having to commit to changing your project for that, then you choose Mac OS 10.6 SDK from the pop-up menu.
These active menu-- active pop-ups, in the overview pop-up is the most common place to see them. Let you-- give you fine grained control over what you build at any given time. Once you build, you need to test. There are three ways to test. You can test before you run.
You can test during your run. And you can test after you ran. Static analysis, you saw yesterday, is a great way to test while you're building to have the compiler tell you the logical problems it sees in your code. Unit tests allow you to test while you're building, then debugging our various-- debugging your debug configuration, debugging release configurations, are ways to test dynamically as you deploy, and then evaluating your application afterwards with instruments.
You'll see more of that later on in the week. Static analysis is a great way to see your code flow and to see logical errors and memory leaks in your code. Unit tests are additional methods, additional software you write in the course of writing your project that run through code while you're building to test the code you've actually built. And your build will fail if your unit tests fail. It's a great way to verify that code remains stable over time. If you change some code and the unit test fails, you know you changed that code wrong.
And then debugging, we have a full interactive debugger which shows you call stacks, it shows calling parameters, it shows you the value of variables as you step through, step-in to step-over, kinds of things we're used to if you've debugged C-based languages before. I want to bring up Rick Ballard again to walk through a demo of building and testing your code.
Thanks Chris. So I'm going to step you through building and looking at build results, handling build errors, debugging a simple problem and some code, and writing some unit tests for that problem.
I want to start out with a simple demo project here which also uses Bezier paths. And let's say that I've been working on this and I built a little view that I'm going to use in this app to display different types of Bezier paths. I've just finished writing my drawRect method, is where I left off. And now I want to see if the code that I just wrote works as I expected.
Well, I can go here and open up the build results window. And this is going to show me in detail what happens when I build. So as you see, when I press Build, you'll see it goes through each of the steps in the build process until it gets to the results. Here it shows me that I've a couple syntax errors. Up here, you see each of the issues of this did and it will highlight them in the source code where the error occurs for me.
You can also see that I have some controls here. If I want to see more information, I can view all the steps in my build. I like to leave it on issues only most of the time because that's usually what you care about. And I can change how I want to view each of the items that show up here.
So these are pretty easy to fix, just got a typo and a missing semicolon. And if I rebuild, you'll see that I know longer have any issues. I don't know if you caught there. It looked like I had a warning in another source file a second ago. But because I didn't edit that source file this time around, it didn't bother recompiling it. And since it didn't bother recompiling it, it didn't report the warning I get.
Now in a lot of places, you have to remember these things. But in Xcode, we make it really easy to go back and find information about older build results that might still be relevant by clicking on the All Results tab. And here you can see even though I didn't just compile this, it'll show me the results that include this random warning and the source file that I'm not using yet.
So now I've got this working, I can go ahead and build and run and bring up my demo app and you can see I can change this zoom and the angle, and switch between a few different types of Bezier curves. Now here, when I click in the line path, you notice that nothing happens, this because I've got a bug in my code here.
So let's go ahead and try and figure where that bug is. I'm going to go ahead and open up my source file and scroll down or actually use the function pop-up to jump right to my drawRect method. Well, that's what's responsible for drawings. So it seems like a pretty good place to start trying to track down the problem. I'm just going to put a breakpoint near the beginning of the method by clicking in the gutter.
Make sure I'll put it one further down. And I'm going to go ahead and-- you see that where it used to say "build and go" in the toolbar, it now says "build and debug." Because when I put a breakpoint in my project, it automatically turned debugging on. If I want to switch back and not use breakpoints, I can turn them off, but this is what I want right now.
So I'm going to go ahead and hit Build and Debug. Now you notice, it's trying to draw right of the bat. So it's in my breakpoint already.
And there's a new toolbar that showed up at the up of my editor that includes some debugging controls. It lets me see the different threads, what my call stack is, and it's got stepping controls and things like that. Now one thing I can do if I want, is press this button to jump to a more traditional debugger window. This is what you saw on the slide and this also shows you your call stack as well as a variable browser so you can look and see what's what. But most of the time, you don't even need that.
We have this thing called data tips, which means I can hover my mouse over any of these variables that are in scope and it will pop up a tip and show me some details about it. Here it shows me that this Rect-- it will summarize its origin and bounds or I can draw them and look at each of these points in detail. Or what I really want to do here, I think, is skip to the end where I'm placing another breakpoint here, I'm going to hit the Continue button.
And let's take a look at this Bezier path that I should have. Well, here's the path. This is the first time that I came up-- we knew that this works. So if I switch to mine and I jump to this last breakpoint, shows the Bezier path. And you see that there is no Bezier path.
I've got a nil path. That's probably why it's not drawing. So I'm going to quickly jump to where I set this path, and I continue again. And let's trigger this breakpoint one more time. So here is where I generate a Bezier path and then set it on myself for later use. You notice if I hover over each of the parts of this line, I get individual step in to controls.
That makes it really easy if I don't want to step into the inner most part of this method to just step in to the outermost part by pressing this button. In this case, I actually do want to step into the inner most part, because that's the method to generate the Bezier curve. So here, I can just start stepping to the method to try and figure out what's wrong.
I switched base in the type of path I want to draw. Oh, and I jumped right to the end. Well, it looks like I just forgot to write the code to generate this particular type of Bezier path. Now, I have code here that I can paste in to fix this, oops, that I can paste in to fix this. But before I do that, I want to make sure that this doesn't happen again. Instead of just fixing my bugs and then giving it the opportunity in the future when I come back and make more changes to this code.
For regression to occur, for my Bezier path not to be generated properly again, I want to point put in a unit test so that I have confidence that I can change the code and know that the things that you used to work still work. And in fact, I'm going to put this unit test in before I put the fix in.
Because that lets me verify that my fix works in the first place. So how do I get started building unit tests? It's pretty easy. First of all, I want to add a unit test target. I'm going to go to the project menu and say, "New target." And you see we have unit tests for both iPhone and Mac OS X, and I'm going to call this "Bezier Tests," this is a name of my target and opens up the target inspector for me, but I don't need that quite yet.
And now, I also need a test case class to run. So I'm going to create a new file from the Objective-C test case class template. And this is a test case for my Bezier view class. So we'll call it Bezier view tests. And you see it gave me a couple of new files here.
And it's ready for me to rate some test. So I'm going to go ahead, and I've already written this test ahead of time. Paste this in. What this test does is, it's going to create a new Bezier view, set the line path type on it, because that's what I'm trying to test here.
Try and generate a Bezier path from that view, and it's going to check and see if the path it got back was nil or not. And if it's not nil, the test will pass. Before I can go ahead and build this, there are a couple of things I need to do. On this code here, I'm referencing Bezier view, that's a class in my applications.
So I need to import it, so that I can actually see the decoration for the class. But my-- oh, another thing I want to do here is make sure that my test case class is included in the right target. So what I did here was get info on the source file, choose the Targets tab, and tell it that it belongs to the tests target. But that's the target that you compile this test. Finally, I need to view the link against that class. But that class is in my applications. It's not in the library.
So there's something I can do. In some cases, you might just compile that class in to your test bundle as well, like if you're doing an iPhone unit test or depending on what your preferences are. The downside of that is that you have to recompile all your classes in your text bundle if you do that. I don't want to do that.
I want to link against my Bezier view class out of my application. And so I'm going to do that by setting a couple build settings in my test bundle. So I'm going to get info on my test bundle and go to the build settings inspector. Now this is a long list of things to search through.
You usually don't want to have to look through the whole thing. Instead, you can use the search field to find what you're looking for. So I'm looking for the bundle loader build setting. And you see when I search to tape that in, it just shows up. It will tell me all about this build setting if I want.
And I'm going to say that the application, my application is the loader for the-- this bundle that'll let me-- that will cause the linker to find classes in it for me. The value I'm going to set here is the path to that application in my build settings directory. It's a special build settings value.
And so I can just set this by double-clicking it and pasting that value. There's one other thing I have to do here which is to set the test host which will this test to run in the application. So, when I run my unit test, it will launch the application, inject the test bundle in to it, and run my test.
And that is also the same application. Now, when I build my test bundle, it's going to want to link against the application. But that means the application is to be built present and up to date. And to make that happen, I'm going to set a target dependency. So here, I click the plus button, add a target dependency on my application.
And now when I build my test target, it will always build my application first. What that means now, is in-- when I make source changes to my application, instead of building the application to see if it worked, I can always build my test bundle. And what that'll do is build the dependent target first, the application target which will build the changes I just made, and then run the test that I have in the test bundle which will verify that the changes I just made didn't break any of my test.
It's a really nice work for once you have this setup just always the test target to build any changes that you have. To do that, I have to set it as the active target and I can use the overview pop-up to do that. So I'm selecting Bezier tests.
So now I've got, in my test target, the source file for my test, a dependency in the application target, I've set my build settings. I should be good to go. When I build this target, a test target has a run script phase as it's the last step which actually runs your test. So all I have to do here is click Builds, and it's building my test target and running my test.
And you can see it's telling me what architecture it's running the test for, what test suite it's running. The test case, it's test new line Bezier path, and the test failed which is what we expected because I haven't added the code to make this test pass yet. So now, I'm going to go and actually implement that type of Bezier path.
[ Pause ]
...and I'm going to go ahead and build again. And you'll see that it rebuilt my application and ran my test and there were no issues. The test passed. And if you want to make sure, you can look at all messages and see that-- yeah, it ran my test, the test passed.
Great! And if you really want to see, you can launch the application. I'm going to turn off breakpoints here, so that it doesn't keep stopping. And it works. So testing is very, very valuable. We encourage you to add unit test to your application and we think that this provides a great environment for you to do that.
Back to you, Chris.
Thank you.
[ Applause ]
Thank you Rick. In 70 minutes, we've taken you from the very beginning of getting your DMG to install your developer tools through creating your first project, going through the editor, navigation, help system, build system, writing unit tests, and debugging an application, and getting ready for delivery. There are a lot of other things to learn about this week. There are some documentation overviews you should read.
I encourage you to read, read, read the online documentation to get an idea. It's a big product. It's a rich product. There's a lot in it. The best way to do-- to learn about it is to sit and read our introductory and overview materials. There are a lot of great sessions at the developer conference. 35