Hour 24. Application Tracing, Monitoring, and Debugging


What You’ll Learn in This Hour:

Image Using the NSLog function

Image Navigating the Xcode debugger

Image Setting breakpoints and watchpoints

Image Modifying variable values on-the-fly

Image Tracing iOS app execution

Image Monitoring memory and CPU usage


Despite our best efforts, no application is ever bug-free. As we end our 24-hour exploration of iOS development, we look at techniques for finding and fixing issues in our applications. The ability to find and eliminate bugs quickly is an essential skill.

Xcode brings together the five basic tools of the software developer’s trade into a single application: the text editor, interface builder, compiler, debugger, and reference documentation. Xcode has debugging tools integrated within it, so all your debugging activities can take place from within the now-familiar interface of Xcode.

This hour covers the debugging and tracing tools included in Xcode. You learn how to use the NSLog function to output debugging information to the Xcode console. You also use Xcode’s debugger to find and correct errors. This will give you a good start toward finding and solving problems that might otherwise lead to hours of head scratching, tears, and extreme frustration.

With the term debugging, it is assumed your project builds with no errors but then encounters an error or otherwise fails to work as designed when it’s executed. If there is an error in your code that prevents it from building, you are still coding, not debugging. The tools in this hour are for improving applications that build but then have logic errors during execution.

Instant Feedback with NSLog

As you’ve developed applications throughout this book, one that has likely become clear is that producing output in an iOS application is more than just saying “print ‘Hello World.’” We must deal with view controllers, scenes, storyboards, labels, outlets, connections, and so on, just to get a bit of text on the screen. This makes the traditional approach of debugging (outputting internal values and messages as a program executes) quite cumbersome. Even if we want to jump through all the hoops of building code and connections to output debugging information, we still have to make sure that none of it appears or interferes with our final production-ready app.

Thankfully, we can quickly generate output from a running application that doesn’t interfere with our interface or application logic. To do so, just enter the humble NSLog function, which you briefly saw in Hour 1, “Preparing Your System and iDevice for Development.” Many a gnarly bug has been slain with just this function alone. At any point in your application, you can use a call to NSLog to confirm the flow of your application into and out of methods or to check the current value of a variable. Any statement you log with NSLog is echoed to Xcode’s debug console.


Why Not print?

Swift also includes the function print, which can be used just like NSLog. So why should we continue to use NSLog, which has been around forever? NSLog automatically adds a timestamp to every line it outputs, which makes it ideal for debugging. In addition, the Swift print statement, while being faster, isn’t thread-safe. This means that if you have multiple methods executing at once, each with its own print functions, the output from one may be mixed in with the output of another, making the whole thing difficult to read.

In many cases, print will work just fine, but NSLog is still the king of printing out text for debugging.


Using NSLog

The NSLog function takes a String argument that can optionally contain string format specifiers. You’ve used these throughout the book to create formatted NSString objects and can get the full list of string format specifiers from the “String Format Specifier” section of the String Programming Guide in Xcode’s Help.

The three string format specifiers you’ll likely need while debugging are %d for integers (often used to debug loop counters and array indices), %f for floating-point numbers, and %@ for any object. Of course, you can also do things “the Swift” way by using string interpolation to substitute your values into an NSLog statement.

Consider the code fragment in Listing 24.1.

LISTING 24.1 Calling the NSLog Function


NSLog("Entering method")
var foo: Int = 42
var bar: Float = 99.9
NSLog("Value of foo: %d, Value of bar: %f", foo, bar)

var name: String = "Klaus";
var date: NSDate = NSDate.distantFuture() as NSDate
NSLog("Value of name: %@, Value of date: %@", name, date)


In this example, the NSLog function is used to output a string, integer, floating-point value, and two objects (a string and a date). The output looks like this:

2015-10-23 10:22:58.133 MyPlayground[2820:308688] Entering method
2015-10-23 10:22:58.146 MyPlayground[2820:308688] Value of foo: 42, Value of bar:
99.900002
2015-10-23 10:22:58.150 MyPlayground[2820:308688] Value of name: Klaus, Value of
date: 4001-01-01 00:00:00 +0000
2015-10-23 10:22:58.151 MyPlayground[2820:308688] foo: 42 bar: 99.9 name: Klaus
date: 4001-01-01 00:00:00 +0000

So, where does this output appear? If it isn’t on the iOS device screen, where can you see the results of using NSLog? The answer is the Xcode debugger console, but rather than just telling you where, let’s see this in action.


Note

When an object is output using either string interpolation or the %@ format specifier, the object’s description method is called; this can provide additional information about the object within the debugging output. Many of Apple’s classes include an implementation of description that is useful for debugging. If you need to debug your own objects with NSLog, you can implement description, which returns a String value.


Viewing NSLog Output

Open the project Counting in this hour’s projects folder. Click Run to start running the application in the iOS Simulator. You’ll see... nothing... just a blank screen with some static text (nothing at all changing on the screen). Behind the scenes, however, the application ran a counter in the view controller’s viewDidLoad method and output the count using NSLog.

If you shift your attention to Xcode, you should be able to see the output in the debug area, as shown in Figure 24.1. If it wasn’t shown automatically, choose View, Debug Area, Activate Console (or press Shift-Command-C). The debug area is usually divided in half—one side for viewing variables, the other (the right side) for showing output. This portion is called the console. You can drag the middle divider to create more room for the console, or you can use the buttons in the lower-right of the debug area to hide or show the left and right columns.

Image

FIGURE 24.1 View the output of NSLog in the console area.


Tip

To quickly access the console area, use the middle button in the Xcode toolbar’s view controls, choose an option from the View, Debug Area menu, or click the hide/show icon (an arrow in a box) at the left side of the debug area.


As you build more projects, NSLog will become a powerful tool in determining that your applications are executing as you expect. It isn’t, however, the most powerful method of debugging an app. For instances where the size or complexity of the application doesn’t lend itself to using NSLog, you’ll want to turn to the Xcode debugging tools, which enable you to view your application as it executes without having to change your code.


Tip

Overwhelmed by output in the debugger console? Click the trash can icon in the lower-right corner to discard any output currently in the debugger console.



Caution: Don’t Go NSLog Crazy

As its name implies, the NSLog function is actually intended for logging, not debugging. In addition to printing the statements to Xcode’s console, the statements are written out to a file on the file system. Logging to the file system is not what you’re intending; it’s just a side effect of using NSLog for debugging. It’s easy to accidentally leave old NSLog statements in your code after you’ve finished debugging, which means your application is taking time to write out statements to the file system and is wasting space on the user’s device. Search through your project and remove or comment old NSLog statements in your application before you build a release to distribute. If you absolutely must leave output active in your code, print will have less of a negative impact on performance in production.


Using the Xcode Debugger

NSLog is a good quick-and-dirty approach to debugging, but it is not the best tool for debugging more complex issues. It’s often more productive to use a debugger, which is a tool that lets you examine a running program and inspect its state. It’s been said that what separates true software development professionals from weekend hackers is the ability to proficiently use a debugger. If this statement is true, you are in luck, because using Xcode’s debugger is not hard.

Normally an application executes at computer speeds, which on an iDevice is millions of instructions per second. A debugger acts like the developer’s brake, slowing down the progress of the application to human speeds and letting the developer control the progress of the program from one instruction to the next. At each step in the program, the developer can use the debugger to examine the values of the variables in the program to help determine what’s gone wrong.

Debuggers work on the machine instructions that are compiled from an application’s source code. With a source-level debugger, however, the compiler provides data to the debugger about which lines of source code generated which instructions. Using this data, the source-level debugger insulates the developer from the machine instructions generated by the compiler and lets the developer work with the source code he has written.

Xcode’s iOS debugger, called lldb, is a source-level debugger. The compiler doesn’t always generate the data needed for source-level debugging. It can amount to a lot of data, and it provides no benefit to an application’s users, so the data is not generated in a release build configuration. Before you can benefit from source-level debugging, you need to build your application in a debug build configuration that will generate the debug symbols.

By default, a new Xcode project comes with two build configurations: Debug and Release. The Debug build configuration includes debug symbols, whereas the Release build configuration does not. Whenever you are working on developing your application, you use the Debug configuration so that you can drop into the debugger whenever you need to. Because Debug is usually the build configuration you want to work with, it’s the default configuration, too. To switch to a release configuration, you must build for an iOS device instead of the Simulator, and you must use the Product, Scheme, Edit Scheme menu to switch to a Release configuration. In Figure 24.2, for example, I’ve set my Scheme so that when I run my app, I will be running it on an iOS device in a Release configuration.

Image

FIGURE 24.2 Set the configuration using the Product, Edit Scheme menu.


Note

Make sure that you remember to use the Release build configuration when you create a version of your application for distribution.


Setting Breakpoints and Stepping Through Code

To use the debugger, you must have something to debug. For the rest of this hour, we work through a few simple debugging tests, starting with a very simple counting application.

Create a new Xcode project with the Single View iOS Application template and call it DebuggerPractice. There is no user interface (UI); therefore, no outlets and actions are required in this exercise.


Tip

The debugger often references source code line numbers, and it is helpful to have these displayed in the gutter. If your Xcode installation isn’t displaying numbers, turn them on by opening the Xcode preferences and activating the Line Numbers option under the Text Editing settings.


Open the ViewController.swift file and begin by adding a new method to the file. This method, describeInteger, returns a string with the word even if an integer passed to it is divisible by 2 or the word odd if it isn’t. Listing 24.2 contains my implementation of this method.

LISTING 24.2 Implementing the describeInteger Method


func describeInteger(i: Int) -> String {
    if i % 2 == 0 {
        return "even"
    } else {
        return "odd"
    }
}


Next, edit the viewDidLoad method. Add a for loop that uses NSLog to display the numbers between 1 and 10 in Xcode’s debugger console. For each iteration of the loop, the method should call describeInteger with the loop’s index. This provides activity that we can monitor in the debugger. Your method should resemble Listing 24.3.

LISTING 24.3 Editing the viewDidLoad Method


override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.
    var description: String
    NSLog("Start")
    for var i=1;i<=10;i++ {
        description=describeInteger(i)
        NSLog("Variables i = (i) and description = (description)")
        NSLog("-----")
    }
    NSLog("Done")
}


After entering the code, take a moment to look at the editor. Notice the light-gray area (essentially a margin) located to the left of your code. This is called the gutter and is where you configure many of Xcode’s debugging features. Figure 24.3 shows the gutter.

Image

FIGURE 24.3 Xcode’s gutter is used for debugging.

Show the debug area, and click the Breakpoints button on the toolbar above the debug area; this enables debugging. Alternatively, you can choose Debug, Activate Breakpoints (Command-Y) from the menu bar. Now start your app. The program starts up and brings us to our application’s empty view.

The output from our NSLog statements is in the debugger console, but nothing else is, as demonstrated in Figure 24.4.

Image

FIGURE 24.4 The debugger is running but not doing anything.

The lldb debugger is running; we just haven’t told it that we want it to do anything. The most common way to start interacting with the debugger is to set a breakpoint in your application’s source code.

Setting a Breakpoint

A breakpoint is an instruction to the debugger letting it know you want the program execution to pause at that point. To set a breakpoint, click once in the gutter next to the line where you want the application to pause. A breakpoint will appear as a blue arrow, as demonstrated in Figure 24.5. Click the arrow to toggle the breakpoint off and on. When the breakpoint is on, it is displayed as a solid blue color. When it is off, it is light transparent blue, and the debugger ignores it. To remove a breakpoint, simply drag it out of the Xcode gutter and it will disappear. While a program is executing, a green arrow in the gutter indicates the current line of source that is active.

Image

FIGURE 24.5 Set a breakpoint by clicking in the gutter.

Let’s create and use a breakpoint. Quit the execution of the application by clicking the Xcode Stop button, and then click the gutter to set a breakpoint next to this line in the viewDidLoad method of ViewController.swift:

NSLog("-----")

Make sure that the breakpoints icon is highlighted in the toolbar (this enables/disables debugging breakpoints), and then click the Run button. Notice that the application stops after printing just one of the inner loop statements to the debugger console:

 2015-10-23 11:25:31.625 DebuggerPractice[3034:319559] Start
2015-10-23 11:25:31.629 DebuggerPractice[3034:319559] Variables i = 1 and
description = odd
(lldb)

The debugger has paused the execution of the application at our breakpoint and is awaiting further direction, as shown in Figure 24.6.

Image

FIGURE 24.6 The debugger pauses at breakpoints.


Note

The Xcode debugger pauses when it reaches a line with a breakpoint, but it does not execute that line. You must manually continue execution for the line with the breakpoint to be run. You’ll see how this works shortly.


Examining and Changing Variable States

Now that the execution of the program is paused in the debugger, we can inspect the value of any variables that are in scope. One of the easiest ways Xcode provides to examine variables is the debugger datatip. Just hover over a variable in the source code of the paused method and Xcode will display a popover, visible in Figure 24.7. For simple variable types, you’ll just see the value of the variable. Objects, however, can display more information, including the class type, and a Quick Look icon for displaying details about the object.

Image

FIGURE 24.7 You can display the datatip by hovering over the variables.

Hover over the i loop counter in the for statement and then the description variable. Notice that the datatip for i is just one level, but the datatip for the more complex String object has multiple levels. Click the disclosure arrows to see the additional levels.

Datatips can also be used to change the value of a variable. Again, hover over the i variable in the for loop statement and click the value in the datatip. It is currently 1, but you can change it to 4 by clicking the current value, typing 4, and pressing Enter. The value in the running program is immediately changed, so the next trip through the loop logs to the console with a value of 5, and there won’t be a logged statement with a value of 2, 3, or 4. To confirm that the program does execute as if the i variable has a value of 4, we need to continue the execution of the program.

Stepping Through Code

By far, the most common debugging activity is watching the flow of your application and following what it does while it’s running. To do this, you need to be able to control the flow of execution, pausing at the interesting parts and skipping over the mundane.

The debugger provides five icons for controlling program execution (see Figure 24.8):

Image Toggle Breakpoints: Toggles breakpoints on and off for the entire application.

Image Continue: Resumes execution of the paused program, pausing again at the next error or active breakpoint.

Image Step Over: Steps to the next line of code in the same method.

Image Step Into: Steps into the method that is being called. If a method isn’t being called on the current line of code, it acts like Step Over.

Image Step Out: Steps out of the current method back to the caller of the current method.

Image

FIGURE 24.8 Program execution control icons.


Note

You’ll notice a sixth and seventh icon beside the Step Out control. The sixth is for debugging application view hierarchies (we’ll see this in a minute). The seventh, a GPS indicator icon, is used to set a simulated location for location services. These features do not affect day-to-day debugging.


Whereas the global breakpoint control is obvious (and useful), the other options might not be so clear. Let’s take a look at how each of these works to control the flow of our application. First click the Continue icon a couple of times. Control returns back to the same breakpoint each time you continue, but if you hover over the i and description variables, you’ll see that i is incrementing and description is switching between even and odd.

Add a breakpoint to this line of code by clicking the gutter:

description=describeInteger(i)

Click the Continue icon again, and this time you’ll see the program stops at the new breakpoint because it’s the next breakpoint the program encounters. This breakpoint is on a line of source where we are calling the describeInteger method. If we want to see what’s going on inside that method, we need to step into it. Click the Step Into icon, and the program stops on the first line of the describeInteger method, as demonstrated in Figure 24.9.

Image

FIGURE 24.9 Program execution after stepping into the describeInteger method.

To step line by line through a method without entering any of the methods that might be called, use the Step Over task. Click the Step Over icon several times to step through the describeInteger method and return to the viewDidLoad method.

Click the Continue icon until you return to the breakpoint on the describeInteger method, and click the Step Into icon to step into the method a second time. This time, instead of stepping all the way through describeInteger, click the Step Out icon and you’ll be stopped back at the line where the describeInteger method was called. The rest of the describeInteger method still executed; you just didn’t watch each step of it. You are stopped where the program flow has just exited the describeInteger method.


Continue to Nowhere

As of the time of this writing, an important feature is missing from Xcode and Swift: Continue to Here. When running an Objective-C project (and hopefully someday Swift), you can right-click in gutter when the application is stopped at a breakpoint and choose Continue to Here. This automatically continues the program’s execution until it reaches the chosen line.

You can currently see this option when working on Swift projects, but it is grayed out and not selectable.


Setting a Watchpoint

Let’s suppose now that there is a tricky bug in your application that occurs only on the 1,000th time through the loop. You wouldn’t want to put a breakpoint in the loop and have to click the continue icon 1,000 times. That’s where a watchpoint comes in handy. A watchpoint is a conditional breakpoint; it doesn’t stop execution every time, it stops only when a condition you define is true.

To test this out, update the for loop to execute 2,000 times rather than 10 times. Your viewDidLoad method should now resemble Listing 24.4.

LISTING 24.4 Updating viewDidLoad to Loop 2,000 Times


override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.
    var description: String
    NSLog("Start")
    for var i=1;i<=2000;i++ {
        description=describeInteger(i)
        NSLog("Variables i = (i) and description = (description)")
        NSLog("-----")
    }
    NSLog("Done")
}


Now let’s set a watchpoint that stops execution when the loop counter equals 1,000. First, remove the existing breakpoints by dragging them out of the gutter. Next, add a normal breakpoint by clicking in the gutter next to this line:

NSLog("Start")

Add a second breakpoint here:

NSLog("Variables i = (i) and description = (description)")

Then right-click the second breakpoint and choose Edit Breakpoint from the contextual menu. The Breakpoints dialog then opens, as shown in Figure 24.10. Here you can use the Condition field to specify when the breakpoint becomes active. Set the condition to i == 1000.

Image

FIGURE 24.10 Program execution stops on the 1,000th iteration.

Click the Run button to execute the application. The program stops at the first breakpoint. Click the Continue icon, and the application will go through the loop 999 times before stopping on the watchpoint on the 1,000th trip through the loop when the loop counter i is equal to 1,000. You can confirm this by looking at the 999 log messages in the debugger console or by hovering over the i variable in the source and looking at its value in the datatip.

Accessing the Variable List

If, at any time, you want to access a list of all variables that are active in your current method, you can do so by viewing the left half of the debugger area. The buttons in the lower-right corner of the debugger toggle the Variable List (left side) and Console (right side). To this point, we’ve been focusing solely on the Console view.

Make sure that the Variable List is visible, and you’ll see that both the i and description variables (and their values) that we’ve been inspecting with datatips are shown prefixed with an L icon, as shown in Figure 24.11. This means these variables are declared locally in the method that is currently executing. You’ll also see A icons for Arguments scope variables that have been passed into the current method as arguments. A pop-up menu at the lower-left corner of the Variable List enables you to show All variables, Local variables only, or Auto—to let Xcode choose what it thinks is relevant.

Image

FIGURE 24.11 Use the Variable List to inspect the value of active variables in your application.


Tip

Expanding a variable line in the Variable List, then right-clicking the value and choosing Edit Value enables you to change it, just as you could through the data.


Using the Debugger Navigators

We first looked at the debugger by examining console output, and since then we’ve focused on debugging in that area alone. There are also two navigator area displays—the debug navigator and the breakpoint navigator—that have some helpful benefits. You may have noticed these appearing on the left side of the Xcode workspace while working with the debugger. You can jump to either at any time by selecting them from the View, Navigators menu.

The Breakpoint Navigator

Large projects with hundreds of breakpoints can get out of hand quickly. Where are all the breakpoints? How do you selectively enable/disable/edit/remove them? The breakpoint navigator, shown in Figure 24.12, is your one-stop shop for managing breakpoints in your project.

Image

FIGURE 24.12 Use the breakpoint navigator to manage your breakpoints.

All breakpoints are listed by the file where they are located. You can click any breakpoint to jump to that spot in your code or right-click any listed breakpoint to manage it (including setting conditions, disabling it, and so on).

The Debug Navigator

The debug navigator displays the application’s call stack listed by thread. A call stack is the list of all the subroutines (methods and functions) currently being executed. Each method in the call stack has been called by the method below it. To better understand this, it is best to see it in action.

Remove the existing breakpoints from your code, and then add a new breakpoint at the start of describeInteger by clicking in front of this line:

if i % 2 == 0 {

Now, execute your code and let the breakpoint take effect. After execution has halted, open the debug navigator by choosing View, Navigators, Show Debug Navigator or by clicking the navigator area toolbar icon (two solid lines with dashed lines in the middle).

Notice that the describeInteger method of our view controller is at the top of the stack and was called by the viewDidLoad method, exactly as we’d expect. The call stack entries listed with a blue icon are code that we have implemented in our project; clicking one of these entries shows a green cursor where the program execution is currently “waiting.” The describeInteger method is waiting on our breakpoint, while the viewDidLoad method waits on the describeInteger method (and so on). Figure 24.13 shows an example of a call stack.

Image

FIGURE 24.13 View the call stack in the debug navigator.

The rows in the call stack that are not in blue are for methods where the debugger only has assembly language available. Click one to see some Assembly code. (Doesn’t that make you thankful that we have a source-level debugger?)

Monitoring CPU and Memory Usage

The Xcode debug navigator has a few other cool tricks up its sleeve. In addition to showing a stack trace, it also shows the CPU and memory usage of your application over time. This can show you whether your application is leaking memory or trying to ask the processor to do too much (eating battery life and leading to poor performance).

To show you how this works, I’ve included a project called CountToDisaster in the Hour 24 Projects folder. This application creates a string, then, every second, sets the string to itself appended with itself (doubling the previous memory usage every second). In a very short time, the application runs out of memory and crashes. As this happens, you can watch the memory usage and CPU usage go up in the debug navigator.

Open the project, switch to the debug navigator, and then click the Run button. Within the Debug Navigator column, you’ll see tiny graphs showing memory and CPU usage as the application runs. Clicking one of these graphs, however, expands to show a detailed dashboard with the actual memory (or CPU) usage and how it compares to the other iOS processes running, as shown in Figure 24.14.

Image

FIGURE 24.14 View your memory and CPU usage in real time.

The CountToDisaster app will eventually crash, and, with more than a gigabyte of memory used when it does, we can definitely surmise that it is a poorly written app! You’ll want to use these tools to verify that your application is a well-behaved iOS citizen, especially if you are using background processing.

Checking Your View Hierarchy

As you build applications with increasingly complex interfaces, it can be difficult to see “what is where.” Is my label not showing because it’s behind something? Is this graphic being cut off by some other object?

These are just a few of the questions that you can answer using the Xcode 6 Debug View Hierarchy feature. This shows an exploded view of the application’s user interface, making it easy to see what elements are coming together to create the interface and how they lay on top of one another.

Because this is a visual tool, the best way to understand it is to try using it. Let’s do that.

Begin by opening the ImageHop application that we built for the iPhone in Hour 8, “Handling Images, Animation, Sliders, and Steppers.” (I’ve included a copy in your Hour 24 projects folder for easy access.) Click Run to start the application, wait until the main field of bunnies is displayed, and then click Debug View Hierarchy in the debug toolbar at the bottom of the Xcode window (see Figure 24.15).

Image

FIGURE 24.15 View your... views.

At first glance, you might think you’re just looking at a normal rendering of your application interface. To see why this isn’t the case, click and drag to rotate the view in three dimensions. You can drag to view the hierarchy from the front, side, back—whatever you want.

Figure 24.16 shows a rotated version of the ImageHop interface.

Image

FIGURE 24.16 Explore how your views are laid out onscreen.

Using the view hierarchy in the debug navigator, you can highlight individual elements making up the view. The controls underneath the view itself can be used to increase the spacing between elements, limit what is visible, or manipulate how the views are rendered for debugging.

I highly recommend testing this feature out, because it will give you a true sense for how your interface layout is actually being rendered and why you may be experiencing visual glitches in your design.

You’ve done enough now to start getting the hang of using the Xcode debugger system. With just these tools for controlling program flow and inspecting and changing program state, you can debug many of the issues that you may encounter as you step into the exciting world of iOS development.

Further Exploration

Invest some time into becoming proficient with Xcode debugging. When you’re approaching the launch date for your application, you’ll want to check and double-check your code. In these cases, time is short and the stress level is high, so it’s not the ideal circumstances to be learning application debugging for the first time. Become comfortable with these tools now, and they’ll provide a significant productivity boost when you need it the most.

Xcode offers many other tools for testing and optimizing your applications, but each could take a book in its own right. The Instruments system, for example, allows you to stress-test your application under a number of conditions and identify potential problems. To get a complete overview of the testing/debugging options available within Xcode and its associated tools (including some nifty UI recording and playback features), be sure to read Testing with Xcode, available through the Xcode documentation.

As you’ve learned throughout this book, Xcode is a large, large product. You’ll be discovering new features for a long time to come. Don’t be concerned if your application development workflow varies from what we’ve covered over the past 24 hours; development is as much a creative process as it is technical. Each developer is unique, and Xcode aims to make each of us empowered and productive.

Summary

In this last hour, you learned how to use NSLog for quick debugging and the Xcode debugger for examining the inner workings of your code. Using a debugger takes much longer than an hour to understand everything it can do for you, but the goal has been to give you enough exposure that you recognize when you need the benefits of the tools.

With that, you’ve reached the end of this book. I sincerely hope that you’ve enjoyed yourself and are ready to write some apps. Remember to visit the support website http://teachyourselfios.com for additional materials and corrections.

Q&A

Q. Why is using a debugger easier or better than just using NSLog?

A. NSLog is a great place for beginning developers to start. It gives a degree of insight into what is going on in the code, without having to change the development process. Using the full-blown Xcode debugger, however, will enable you to view and modify values in your code as it is running. In addition, it doesn’t require any changes directly to your code, so there isn’t a need to remove debugger statements when the code is clean. Using a debugger takes awhile to get used to, but for large projects, it is a must.

Workshop

Quiz

1. NSLog is beneficial for debugging because it includes which of the following?

a. A timestamp

b. Syntax highlighting

c. Object rendering

d. Graphic output

2. A location within your code at which application execution is halted for the purpose of debugging is called a what?

a. Halt spot

b. Breakpoint

c. Stop point

d. Pause place

3. What is the debugger you will use in Xcode called?

a. ggdb

b. gdb

c. ldb

d. lldb

4. Breakpoints are set by clicking within what in the Xcode?

a. Column

b. Margin

c. Gutter

d. Divider

5. NSLog statements should not be included when doing what with applications?

a. Developing

b. Shipping

c. Debugging

d. Testing

6. You should use which configuration when preparing an application for submission to the App Store?

a. Release

b. Debug

c. Test

d. Production

7. You can use lldb to inspect your application on a line-by-line basis because it is what type of debugger?

a. Source-level debugger

b. Code-level debugger

c. Statement-level debugger

d. Edit-enabled debugger

8. To figure out where your application has been set to halt for debugging, you can use which of the following?

a. Breakpoint navigator

b. Debug navigator

c. Stack trace

d. Instruments console

9. To view your application’s UI split into a 3D view of layers, you may take advantage of which feature?

a. lldb

b. Debug console

c. Debug View Hierarchy

d. View Layer Inspector

10. The debug feature that enables you to skip a method is called what?

a. Breakpoint inspection

b. Continue

c. Step into

d. Step over

Answers

1. A. The NSLog function includes a timestamp in all output, making it a handy tool for debugging.

2. B. Breakpoints are the spots in your code where execution should be halted for the purposes of debugging.

3. D. Xcode’s debugger is named lldb.

4. C. Click within the Xcode gutter to set a breakpoint.

5. B. Shipping applications should not include NSLog statements because they log to the file system and slow down application execution.

6. A. A Release configuration should be used with applications that are going to be submitted to Apple for listing in the App Store.

7. A. The lldb debugger is a source-level debugger, making it possible to inspect your application code in Swift (not machine language!) as it executes.

8. A. The Breakpoint Navigator shows all the breakpoints that have been configured in your application, across all the files.

9. C. Use the Debug View Hierarchy feature in Xcode 6+ to view a 3D diagram of your application’s user interface.

10. D. The Step Over function enables you to skip the execution of individual methods during debugging.

Activities

1. Try breaking applications by using the debugger to set values outside their bounds—text in numeric fields, loops that extend beyond their endpoint, and so on. How does Xcode react?

2. Use the debugging tools to monitor the inner workings of the applications you built earlier in this book. Then take a break, eat a sandwich, and take a walk outside.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.119.14.235