Xcode 4 brought forth a number of changes to the look and feel of Xcode as well as changes in functionality. As with any major change to the way people do things, it was met with mixed reviews and some complaints. In this chapter, we'll steer clear of the shortcomings of Xcode 4 and insted focus on its strengths and improvements, which are many.
The very first thing you'll notice about Xcode 4 is its unified interface window. Everything has been brought into one window, and the new interface has introduced the common interface element of tabs instead of multiple windows.
Figure 1–1 shows an example of the Xcode user interface, including its various display panes. These panels help you to navigate, build, and debug your application. Their visibility can be adjusted easily using the View buttons in the upper right-hand corner in order to provide more viewing space for the Editor.
Even Interface Builder has been included in the single window interface of Xcode 4. With the inclusion of Interface Builder, Apple has built some swift functionality to help you go from visual interface to functioning code. Figure 1–2 shows Interface Builder being used to construct an application's user interface. This will be covered more in Chapter 2.
With the Assistant Editor, you can easily see two related files side by side. This is very useful when working with class headers and implementation files because you can easily modify both files in a single view. By using the small navigation area at the top of each pane, you can either select specific files to show together, or specify “Counterparts” to automatically show the related header or implementation file, as shown in Figure 1–3.
A feature of Xcode 4 that is sure to save you time is Fix-It. This feature tries to detect common programming mistakes and offers suggestions on how to fix them. It does this while you are writing the code rather than waiting for you to run a build command. This makes it a great time saver for common mistakes.
Xcode 4 also features better source control integration with Git. You are now given the option to create a local Git repository every time you start a new project, and modified files are clearly marked in the Navigator pane. The Timeline Editor view will even show you changes that you've made since the last check-in or compare your current file to any past file version in the repository. This view back in time is very similar to the Time Machine backup interface in Snow Leopard, as shown in Figure 1–4.
Offering a lite version of your app is a great way to give customers a chance to try your app before buying it. Maintaining two code bases, however, can be quite tiresome and get out of hand as you implement new features into your app. While the ability to maintain two build targets was available in Xcode 3, Xcode 4 has made it even easier.
Select your project file in the Navigator area, and then select the build target for your project. Now press D to duplicate the target. You will be prompted to “Duplicate Only” or “Duplicate and Transition to iPad.” Click Duplicate Only to create a new target that will be used for your Lite build, as shown in Figure 1–5. This will result in a separate build target with which you can implement a second version.
Rename the new target with an appending “Lite”. You will also want to go to the Build Settings tab and find the Product Name attribute under the Packaging heading in order to append “Lite” to the app name. Now that the build name is set, you need a way to differentiate between the two builds in your source code. For that, scroll down and find the Preprocessor Macros, and add a new macro named LITE_VERSION
. Make sure to add the new macro for the Debug and Release build settings. Figure 1–6 shows an example of these changes.
If you build and run that now, you will end up with a second app on your device with the name “SampleApp Lite” as the title, but it runs the same code as the regular version of the app, as demonstrated in Figure 1–7. Keep in mind that the two targets must have separate bundle identifiers in order to show up as separate apps. This is the default setting, but be careful when making changes.
To build different features into your app, you will need to utilize that preprocessor macro you created. Anywhere in your code that you want to specify different code for your lite version vs. the full version, use the following #ifdef
directive:
#ifdef LITE_VERSION
//Stuff for Lite version
Self.labelAppName.text=@”Sample App Lite”;
#else
//Stuff for Full version
Self.labelAppName.text=@”Sample App Full”;
#endif
Build and compile the two apps on the simulator, and you will see that the apps change the code they compile and run based on the preprocessor macro and the power of the #ifdef
directive. Figure 1–8 demonstrates the result of this configuration.
NOTE: You can also control what files are included in each build. For instance, you may not need to include the full version artwork in the lite version. Click your Lite project target and go to the Build Phases tab. Now expand the Copy Bundle Resources ribbon, and remove or add any files that are specific to the lite version.
Occasionally, you will run into an error described only as “EXC_BAD_ACCESS
,” and unfortunately, it doesn't tell you in which line the bad access is occurring. This is caused when you have released a variable and then tried to access that freed object. When an object is no longer there and you try to access it, the term is a zombie object. Enter the zombie hunter, the NSZombieEnabled
flag. This is not new to Xcode 4, but where you set the flag can be difficult to find in Xcode 4. Go to the Product menu and select “Edit Scheme…”. Now select the Run step and click the Arguments tab. Under the Environment Variables section, add NSZombieEnabled and set the value equal to YES, as shown in Figure 1–9.
The next time you run your code, the zombies will be identified in the Debug window. Figure 1–10 displays an example of a zombie caught by Xcode.
Version control can be a daunting concept to new developers, but it is something worth learning. Once you have started using version control, you will wonder how you ever got along without it. Its benefits for teams of developers are fairly obvious. Individual team members can work on different parts of an app without stepping on each other's code.
Single developers can benefit from version control as well. With multiple branches, you can add features to your app without disturbing the previous released version. If a bug is discovered in your released version, you can switch branches and fix the bug without impacting the future version of your app. Then you can merge the two versions and have a new version that contains the bug fixes and the new features. All the while, you can reach back to any point in time and see changes that were made to your code.
Xcode 4 introduced version control into the Xcode environment. Initially, it supported only local Git repositories, but Xcode 4.2 has brought remote repositories to the environment. This is great news if you are part of a development team or if you work on multiple machines. Remote repositories also provide a safe place for your code in case of computer failure or loss.
Whenever you start a new project in Xcode 4, you are given the option to create a local Git repository, as shown in Figure 1–11. If you select this box, Xcode will create the local repository and automatically add the project files it thinks are necessary.
As you make changes to your project and its files, their source control status will be displayed in the navigator window. “A” is for when a file has been added to your project, and “M” is for when it has been modified since the last check-in. Figure 1–12 shows a navigation pane with multiple files with these statuses.
You can filter the navigator contents so that you see only the files that are pending changes to the source control repository by clicking the middle icon in the bottom of the navigator pane, as shown in Figure 1–13.
To commit your changes back into your local repository, go to FileSource Control Commit or C. The Commit window will be presented. By clicking a modified file, you will see your edited version in the left pane and the current version in the repository in the right pane. All of your changes will be highlighted so that you can easily see the differences between the two files. Figure 1–14 displays such a window with highlighted changes.
Worth mentioning is the fact that the left pane is a live editor, so if you see something that should not be committed, such as an NSLog
statement, this is your chance to comment it out or make the necessary changes.
Xcode does a good job of suggesting which files should be committed. You do not want to version control your workspace file (*.xcworkspace
) or your userdata directory (xcuserdata
). Generally Xcode will not check those files, and you will note the “?” mark icon next to the files. This means they are not currently under version control, nor should they be. Figure 1–15 shows these non-version-controlled files/directories.
At the bottom of the commit window, as shown in Figure 1–16, is where you need to enter a message about the changes you have made before committing. Your commit message should be a descriptive summary of the changes you have made to your code, such as “added such and such feature.”
Branches are copies of your project that you can work on without disturbing the main branch, also known as the master branch. They allow you to add features and fixes without affecting the main build.
To manage your repository, you can go to Window
Organizer
or 2 and click the Repositories tab. In this view, you will see a list of repositories that Xcode knows about. As shown in Figure 1–17, you can click the Branches
folder under a repository to see a list of branches available to Xcode for this repository.
When you select a branch, you will see a list of the latest commits to that branch. The information includes who made the commit and their commit message.
Create a new branch to start adding a main menu to your app. Click the Add Branch button at the bottom of the Organizer window. In the window shown in Figure 1–18, type a branch name and click the check box next to “Automatically switch to this branch”. This will duplicate the code in the master branch into a new branch called “MainMenu,” and then it will switch you to that branch.
Now that you are working in the MainMenu branch, you can add a new view controller for the main menu without affecting the rest of the app source code. After adding the view controller and coding it up, you can commit this back to the source code repository. Again, this will affect only the MainMenu branch and not make any changes to the master branch.
To merge the two branches, you want to switch to the branch that you want to merge the changes into. You are done coding up the MainMenu, and you want to put it into the master branch, so you are going to switch to the master branch. This is done from the Organizer window, so press 2.
Click the project folder, and then click the Switch Branch button on the bottom right. Select the branch you want to switch to—master in this case—and click OK. This will switch your active branch back to the master branch, and now you can merge the two branches together. Figure 1–19 highlights these steps.
Go back to the Xcode window and click File
Source Control
Merge.
You will be prompted to select which branch you want to merge into the current branch (master), as shown in Figure 1–20. When you click Choose, you will see the commit changes window.
This commit changes window is very similar to the one you saw before with one minor change: at the bottom of the code review panes, you will see four icons. If each branch contains a file that has been modified in both branches, these icons will allow you to decide which one takes precedence. The icons are, in order from left to right, “Merge the left file first and then the right,” “Keep the left file changes only,” “Keep the right file changes only,” and “Merge the right file first and then the left.” These icons are shown in Figure 1–21. This is very useful for resolving conflicts if two people have made changes to the same file or if a file has been modified in both branches.
Clicking the Merge button will combine the MainMenu branch into the master branch. If you look at the master branches commit history in the Organizer view (2), you will see that the commits from the MainMenu branch have been combined with the master branch commits.
Up until this point, you have been working with local repositories. In Xcode 4.2, support for remote repositories was added. This allows you to store your code online where you can get to it from any computer and allows multiple users to access your code. Another benefit of remote repositories is storing your source code offsite in case of sudden device failure or worse.
To add a remote repository, go to the Organizer view (2) on the Repositories tab and select the repository you want to add a remote option to. Click the Remotes
folder under the project repository, and click Add Remote at the bottom. This will bring up a view similar to Figure 1–22. Enter a name for your remote repository and the location, and then click Create.
Now that you have a remote repository, you can push and pull your code from the remote repository to keep things up to date. This is not the same as a commit. A commit or merge affects only your local copy. You need to then push your code to the remote repository to update the remote repository.
A very popular online repository for Git projects is GitHub, found at www.github.com
. GitHub offers the ability to remotely store your code in either a public or private repository. This allows small teams of developers to work on one project together or individual developers to remotely store their code repository. Up until now, you had to use third-party software or the command-line version of Git to push your changes to a remote repository. With the inclusion of remote repositories in Xcode, it's easy to work with GitHub and to store your source code remotely.
Before you add the project to Xcode, you should create a repository on GitHub. You'll need an account on GitHub to do this; follow the very detailed instructions to set up your account. Once you've created a repository on GitHub, copy the entire HTTP access path on the Source tab, as shown in Figure 1–23. This will be the remote location of your repository.
Setting up GitHub in Xcode is very similar to setting up any remote repository. Go to the Organizer view (2) on the Repositories tab, and select the Remotes
folder beneath the repository you want to add to your GitHub repository. Now click Add Remote at the bottom of the window, paste the HTTP location into the location field (as is done in Figure 1–24), add a name, and click Create.
After clicking Create, you will see a place to enter your GitHub credentials at the bottom of the Organizer window. Your username should already be filled in, so all you need to enter is your password. Now go back to your main Xcode window, and use File
Source Control
Push. In a window reflecting Figure 1–25, you will be prompted to select the remote repository to push the code to. Select the GitHub repository, and click Push. Xcode will now send your code to your GitHub project repository. Using the GitHub web interface, verify that your changes and changelog have been uploaded properly. Now other developers can check this code out using their own GitHub accounts and the File
Source Control
Pull...
menu option.
These are some tips for working with source control repositories:
Xcode 4.2 introduced Automatic Reference Counting (ARC) as a way to help developers focus more on writing great apps and spend less time on memory management. As any developer new to Objective-C, and some who have been at it for a while, you will likely struggle with memory management concepts. Retain
this, release
that, autorelease
what? If those three methods baffle you, then fear not, Xcode 4.2 is for you! Even if you are comfortable with memory management, you will see benefits from migrating your code to using ARC.
ARC is a compile time memory management method. It does not add performance overhead to your running apps because it is compiled into the code before you build it. This is a different concept than garbage collection, a method of memory management that Java developers are familiar with. With ARC, the compiler (LLVM version 3.0) automatically adds retain and release calls by analyzing your objects and determining when objects are no longer referenced. While a pointer to an object exists, the object will exist. After it has synthetically added the memory management methods, it compiles the binary for running and deployment.
Without ARC, the following code would produce a memory leak because the return value is not autoreleased:
-(NSString *) cityStateZip {
return [[NSString alloc] initWithFormat:@”%@, %@ %@”, self.city, self.state, self.zip];
}
Without any changes to the code, ARC will compile this method and add the autorelease at compile time to remediate the memory leak.
The following are some rules to follow while working with an ARC-enabled project:
retain
, release
, or autorelease
in your code. You cannot override or implement these methods either.release
statements are no longer needed, you must no longer implement a dealloc
method in your classes.NSString *B = (NSString *)A;
The solution is to use the __bridge
directive:
NSString *B = (__bridge NSString *)b;
NSAutoreleasePool
; instead you can use @autoreleasepool
.Every new project template in Xcode 4.2 uses ARC and the LLVM v3.0 compiler by default. There is nothing special that you need to do. ARC-enabled projects are also compatible with iOS 4.
One day, we will look back and not even remember writing code with retain
, release
, and autorelease
calls. Until that day, we'll need to work on existing projects and migrate to the ARC method of memory management to keep them current and to also take advantage of the performance improvements. Apple highly encourages that all projects move to LLVM 3.0 and ARC. They have provided a way to convert your old projects to use ARC.
Open your old project and make sure it builds correctly before you make any changes.
NOTE: This might also be a good time to commit your changes to your Git repository and push your changes to a remote repository for safekeeping.
Next go to Edit
Refactor
Convert to Objective-C ARC.
Xcode will ask you which targets to convert. Select your targets and click Precheck. Figure 1–26 shows a sample target selection.
NOTE: Make sure you are set to build for device and not the simulator.
Figure 1–26. Selecting targets to convert to ARC
The precheck will begin and analyze your code to see what changes need to be made to your project before the conversion can begin. A notification will be displayed if there are issues, as shown in Figure 1–27; you can see them in the navigator pane under build results, an example of which is shown in Figure 1–28.
You will need to correct any issues before proceeding with the conversion. Once the issues have been corrected, you will be prompted to start the conversion. Figure 1–29 shows a window detailing the conversion process. The first step is to take a snapshot of your application's source code so you can revert back. The next window will show you any changes that are going to be made to your code. It is the same window that you have seen when you commit changes to a source control repository. The most common changes include removing dealloc
methods and autorelease
and retain
statements. Properties are also specified to be either “strong” or “weak.” “Strong” corresponds to the former “retain” statement, while “weak” results in immediate de-allocation of an object as soon as no other strong pointers refer to it.
After you have reviewed the changes, you can click Accept, and Xcode will make the necessary changes. Build your project, and make sure it builds correctly after the changes have been made.
You can verify that your project is using the LLVM 3.0 compiler by checking your target compiler settings, as shown in Figure 1–30.
To verify that you are using ARC in your project, navigate to your target Build Settings and go to the “Apple LLVM compiler 3.0 – Language” section. You should now see the Objective-C Automatic Reference Counting setting is equal to Yes. Figure 1–31 demonstrates this verification.
Xcode has a variety of intricacies built into it that can greatly improve your development experience. Listed in this section are a few shortcuts meant to expedite common tasks and make building applications a simpler process.
To quickly comment out a block of code, select the code with your mouse and then press / on the keyboard; each line will be commented out. Need to turn the comment off? Just repeat the procedure and the lines will be uncommented.
Xcode 4 improved greatly upon the previous autocompletion functionality that works as you type. This is a big help to let you know what methods are available and to increase your coding efficiency. If the autocomplete isn't showing up or you want to know what is available for an object, hit the Esc key to bring up a list of available methods.
Xcode 4 does a pretty good job of managing your indents, but if you ever find yourself needing some custom indentation or to manage your own indenting, use [ to unindent and ] to indent manually. This works great for blocks of code as well; just select the block with your mouse and use the keyboard shortcuts.
You have just added a new property or object to your class header file, and now you want to switch to the implementation file to start writing the code for that object. Pressing ^+Up/Down will switch you between the two files. Figure 1–32 displays a common use of the Assistant Editor.
Xcode 4 also offers a new split pane view that will show related files, called the Assistant view. To enable this view, you can click the Assistant view icon at the top of the screen, or press ⌥+,(option+command+comma) to load the Assistant view.
NOTE: The keyboard shortcut works best if you are looking at the implementation file; execute the command, and it will automatically load the header file in the right pane.
Can't remember all the properties or methods of a class? You can get a reminder with a -click of an object type, and a pop-up will be displayed with a description of the object, as shown in Figure 1–33. From this pop-up, you can also view the object's documentation or the header file.
A similar shortcut is to -click any object or class to jump to its definition.
You can -click any file in the navigator pane to open it in the Assistant Editor. You can also -click any file, and a diagram, such as that shown in Figure 1–34, resembling the Xcode interface will pop up. Select a region in the diagram to open the file in the corresponding pane in Xcode.
Xcode 4 introduced behaviors to the editing interface. These allow you to run custom commands or scripts when performing actions in Xcode. Access behaviors by going to Xcode
Behaviors
Edit Behaviors.
Figure 1–35 shows the resulting opened window.
You can customize the actions available on the left side of the pane with behaviors found on the right pane. For instance, one behavior that I like to use is to open a separate tab that contains build errors. This preserves my editing tab and allows me to pick up where I left off after the build succeeds, or fails, as is usually the case. The behavior in Figure 1–35 will create or show the tab named Build Results, show the Issue navigator, show the debugger pane, and navigate to the first issue found (if any).
You can also add custom behaviors that are performed with a shortcut key. Click the + at the bottom of the behaviors pane, and set a name for your custom behavior. Now click the command key symbol () at the end of the line to set your keyboard shortcut.
Apple has provided iOS developers with an updated application development environment in Xcode 4. While not perfect, it does offer many improvements over previous versions and is worthy of some praise. The transition between Xcode 3 and 4 may be difficult and time-consuming, but once you have been converted, you will be writing code more efficiently and easily in the new interface.
New enhancements, such as source control with remote repositories, will make your project development with teams more seamless and provide independent developers with the ability to remotely store source code for safekeeping.