Talk Funnel

Ramin Firoozye's Public Whisperings

Archive for the ‘cocoa’ tag

NSArray debugging on the iPhone

without comments

If you’re debugging on the iPhone and encounter a lot of NSArray objects, you’ll notice that dumping out the contents doesn’t give you too much information. To help remedy this situation, I whipped out a quick-and-dirty ‘helper’ to show a bit more detail. As with the UIView helper all you have to do is include the NSArrayDebugExtras.m file in your project and build it. This works through the standard Objective-C category mechanism by adding an extra method to an existing class.

To use it, set a debugger breakpoint and enter:

(gdb) po array-variable-name

What you will get is a recursive dump of the array and its contents. If the array contains strings, labels, text fields, or text views, the actual text value is shown. If it contains other arrays, it recursively walks down the array of arrays and shows the contents.

Since there’s no garbage collection on the iPhone, probably the most useful information is the retainCount for each array and item.

If the array contains a lot of custom objects, of course, you’ll only see rudimentary information. In that case, I suggest you make a point of defining a debugDescription method for each object so the contents can be properly shown.

Of course, you’re welcome to tweak the display format to show whatever information makes sense to you, but this should give you a good starting point.

[ Download: NSArrayDebugExtras.zip ]

Update: The [obj className] method is no longer accessible. Fortunately, the runtime function object_getClassName(obj) provides the same service. The attached code has been updated. Thanks to Howard Katz for noticing the problem.

Written by ramin

February 15th, 2009 at 4:42 pm

Posted in Tech

Tagged with , ,

Easy UIView debugging on the iPhone

with 5 comments

The user interface of the iPhone is based on a series of nested UIView objects, arranged in a view-subview/parent-child relationship. When building a complex application with a lot of views, sometimes it’s handy to be able to see exactly what that relationship is.

But if you try to print out the value of a UIView in the debugger (or through an NSLog function) you’ll be sorely disappointed. In this example we have a variable called front that is derived from a UIView. Setting a breakpoint in the XCode debugger, I type in a po (print object) command to show what that variable contains:

(gdb) po _front
<BCCardSideView: 0x106b020>

What you see is that the variable is of type BCCardSideView and its hex address. Not very helpful.

One solution is to take advantage of the Objective-C dynamic runtime and override UIView’s default describe method. This is the method that is called every time you try to display the value of an object. Here we have just such an override that recursively walks the view tree and dumps out the values. The code is contained in a file called UIViewExtras.m. All you have to do to enable it is include the file in your XCode project. There are no explicit methods to call.

Here’s the same output after UIViewExtras.m is included in the project (the indentation is a little messed up because of the column width of this blog. In the debug window, it should look fine):

(gdb) po _front
+ BCCardSideView retain:3 - tag:0 - bgcolor:(r:0 g:0 b:0 a:1.00)
bounds: x:0 y:0 w:130 h:80 - frame: x:5 y:5 w:130 h:80 - center: x:70, y:45
++ BCCardBackgroundView retain:4 - tag:0 - bgcolor:(r:255 g:255 b:0 a:1.00)
bounds: x:0 y:0 w:130 h:80 - frame: x:5 y:5 w:130 h:80 - center: x:70, y:45
++ BCCardTextView retain:4 - tag:0 - bgcolor:(r:0 g:255 b:255 a:1.00)
bounds: x:0 y:0 w:100 h:20 - frame: x:0 y:0 w:100 h:20 - center: x:50, y:10
text (len:4 - color:r:0 g:255 b:0 a:0.00): 'name'
++ BCCardTextView retain:4 - tag:0 - bgcolor:(r:255 g:255 b:0 a:0.00)
bounds: x:0 y:0 w:100 h:20 - frame: x:0 y:20 w:100 h:20 - center: x:50, y:30
text (len:5 - color:r:0 g:255 b:0 a:0.00): 'title'
++ BCCardTextView retain:4 - tag:0 - bgcolor:(r:0 g:0 b:255 a:1.00)
bounds: x:0 y:0 w:100 h:20 - frame: x:0 y:40 w:100 h:20 - center: x:50, y:50
text (len:5 - color:r:0 g:255 b:0 a:0.00): 'email'
++ BCCardTextView retain:4 - tag:0 - bgcolor:(r:255 g:0 b:0 a:1.00)
bounds: x:0 y:0 w:60 h:20 - frame: x:0 y:60 w:60 h:20 - center: x:30, y:70
text (len:7 - color:r:0 g:255 b:0 a:0.00): 'phone.1'

For each view object you see:

  • The retain count.
  • The tag value (if specified).
  • The background color value in RGBA. RGB values are scaled up to 0..255 and alpha is shown as a floating point value between 0 and 1.
  • View bounds rectangle (x, y, width, height)
  • View frame rectangle (x, y, width, height)
  • View center (x, y)

If view is a UILabel or UITextField, you also get:

  • - Length of text
  • - RGB value for text itself (vs. the background)
  • - Actual value of the ‘text’ inside the field.

Subviews are indented by multiple “+” (plus) signs. So the top-level has one ‘+’ all its subviews have two ‘+’ signs, *their* subviews will each have three ‘+’ signs etc.

I personally find this handy in debugging views — especially those created dynamically. I hope you do too.

[ Download: UIViewExtras.zip ] (Update: Link updated.)

Update 2 [06-Oct-09] : Modified method of obtaining class name so it should work with newer SDK releases.

Written by ramin

December 11th, 2008 at 2:49 am

Posted in Tech

Tagged with , ,