Using the Expressions Window

Xcode is a fantastic debugging environment. It provides we (developers) with a slew of tools to find problems in our code and fix them. However, many of these tools go unnoticed by developers and with that the potential to find and fix bugs more painlessly is lessened.

I posted a question on twitter last week asking if other iPhone developers would find a quick tutorial on the Expressions window useful. Most people responded that they didn’t know what the Expressions window was, and so it was decided.

Who

You.

What

The Expressions window is a debugging window that can be opened in Xcode when you’re running your app in the debugger. I use it to supplement the general debugger window.

Why

If you hit a breakpoint and open the debugger window (Run -> Debugger), you’ll find a list of local variables and member variables along with their values. This is valuable information. However, often information we’re interested in, especially in Objective-C objects, isn’t available in this window. NSObjects that you haven’t created, things like UIKit objects in particular, often hide their data objects from the debugger and you can only access them through properties. These often don’t show up in the debugger window when you hit a breakpoint. The Expressions window will often give us the information we need.

Where

Run your app (on your device or simulator, it doesn’t matter) and set a breakpoint where you’re interested in some value. When you hit the breakpoint, open the Expressions window (Run -> Show -> Expressions):

Finding the Expressions window

This will open up a small window that looks like this:

Expressions Window

When

I’m going to set up a small app that will do some dumb stuff upon loading its root view controller. It will run this code in viewDidLoad:

 NSString* myString = @"This is an example string.";
 NSArray* myArray = [[NSArray arrayWithObjects:@"Zero", @"One", @"Two", @"Three", @"Four", nil] retain];
 [myArray retain];
 
 int arrayCount = [myArray count];
 arrayCount++;
 
 NSDictionary* dict = [NSDictionary dictionaryWithObject:@"value" forKey:@"key"];
 
 int myCArray[] = {
     0, 1, 2, 3, 4, 5, 6,
     7, 8, 9, 0, 1, 2, 3,
     4, 5, 6, 7, 8, 9, 0
 };
 
 [myArray release];
 [myArray release];

I’m going to use this code to show how to use the Expressions window. I’ve set a breakpoint at the first [myArray release] line. When I hit it, the debugger window looks like this:

Debugger

Notice that the debugger was able to display the value for myString, but it wasn’t able to display the string values for the strings inside the myArray array. Now if this were a real app and you needed to know what was in that array, you could be in trouble. Or say you want to know the retainCount of your array. What do you do? You can probably guess where I’m going with this: Expressions window to the rescue!

How

So you’re probably wondering how we actually use this magical debugging window. It’s easy. The Expressions window does exactly what it says it does: it evaluates expressions. This means that you can do a lot with it that you can’t do with the general debugger. You can type in math equations and have it evaluate the answer. You can call methods and have it give you the return value. These are very powerful tools.

In my example, say arrayCount is used in some math expression to determine how many items to delete later on. I can enter the calculation into the Expressions window, and it will tell me the answer. The cool thing is that I can leave it in the Expressions window and next time I hit this breakpoint, it will update the expression and give me the new answer!

To enter an expression, just type it into the text field at the bottom of the window and hit Enter. Here you can see I’ve entered two expressions: the first is just the name of the arrayCount variable, and the 2nd is an equation using the variable in it.

Doing Math With Variables

Pretty cool! Now let’s find out what the string values inside the array are. I really only care about the first one in the array, so I’m going to ask the array for the object at index 0 and then cast it to an NSString*:

Calling a Method in the Expressions Window

What’s really cool about this is that I’m calling a method on the myArray object and displaying the result. Again, if I leave this in the Expressions window, the next time I hit the breakpoint, this value will update with the current value.

Let’s take advantage of this new found ability to call methods at run-time and check the retain count on our array:

Checking the retain count

Notice that I had to cast the return value of [myArray retainCount] to an int. If I hadn’t done this then the Expressions window would have displayed no value, and displayed “out of scope” in the Summary. It says it’s out of scope because it doesn’t know how to treat the return value. By telling it that it’s an int, it knows how to deal with the value that comes back.

(Aside: For those of you who are familiar with GDB debugging, you’ll notice something awfully suspicious: these look like expressions you could enter at a GDB prompt. The only difference is that we’re omitting the “print” command that would usually preface the command. The benefit of using this over GDB, is that the Expressions window can remember all of your commands and update them the next time you hit the breakpoint.)

NSDictionary is a tricky object to work with. It’s very difficult to get debugging information out of it. The best way is still probably logging, but if you’re in a jam, you can get access to information about the dictionary using the Expressions window (look at all this fun casting!):

Getting info on an NSDictionary

Finally, if you’re working with straight C-style array (not NSArrays) that are very large, and you want data on very specific index ranges, you can do some fun things here. Let’s say you want to get 3 values out of the myCArray starting at index 5. Easy peasy! The ‘@’ symbol comes to the rescue. To access n elements starting at index m, enter “myCArray[m]@n”:

C Arrays

Wrapping Up

Hopefully this should get you started and you can start playing around with it on your own. If you’re looking for more resources, it’s often helpful to search for GDB commands (e.g. searching for “GDB array” will turn up resources on using the “@” symbol for C-arrays).

A Word of Warning

Be very careful leaving expressions in the window between runs of the application. Certain expressions, if left in the window, will cause the app to crash at launch when the debugger tries to evaluate them. So, if your app starts crashing on launch and you’ve been messing around in the Expressions window, open it up and delete everything in there, and launch again.

Also, if you enter an expression that causes something to evaluate which causes an exception, you can cause the debugger disconnect from the app. It just means that you’ll have to relaunch the app, but it can be a pain if you’re in the middle of tracking down a rare crash bug and you suddenly lose your connection to the app mid-debugging.

Happy hunting!

Owen