Quick and easy debugging of unrecognized selector sent to instance

It’s happened to all of us; we’re merrily trucking down the development road, building and testing our app when all of sudden everything grinds to a screeching halt and the console tells us something like:

-[MoneyWellAppDelegate doThatThingYouDo]: unrecognized selector sent to instance 0xa275230

Looking at the Xcode backtrace doesn’t seem to help either since it most likely looks like so:

 

At this point you start the hunt through your code looking to see who sent the -doThatThingYouDo message. You may find the answer right away and things may be all hunky dory, or you may spend the next hour trying to figure out where the hell that call is coming from.

The good news is there is a better way. All you need to do is pop over to the Breakpoint Navigator, click the + button at the bottom and choose Add Symbolic Breakpoint…

In the Symbol field enter this symbol:

-[NSObject(NSObject) doesNotRecognizeSelector:]

Now when any instance of any object within your program is sent a message to which it does not respond you will be presented with a backtrace that takes you right to the point where that message was sent.

 

Cheers and happy debugging.

Quick and Easy Drawing Performance Debugging with NSShowAllDrawing

While watching one of the WWDC09 session videos I was informed of a great tip that I had been previously unknown to me: Pass -NSShowAllDrawing YES as an argument to your application in Xcode to see a visual representation of the drawing that your application performs as it runs.

To illustrate how NSShowAllDrawing works and the issues it can help you correct I’ve put together two videos.  The first shows my app, Bezipped, in its current 1.0 state and its current drawing behavior.

This second video shows how I improved the drawing in Bezipped simply by setting the top-level container to be backed by a Core Animation layer:

I highly recommend giving your app a spin with NSShowAllDrawing if you haven’t already, it was certainly a real eye-opener for me.  There are some additional resources for debugging your drawing performance on OS X (as pointed out to me by André Pang) provided by Apple here: Drawing Performance Guidelines: Measuring Drawing Performance

Lastly, both Alan Rogers and Steve Streza pointed me towards Quartz Debug.app (included with the developer tools) as another means to see similar redrawing behavior.  I found Quartz Debug’s options to be a bit heavy-handed as the drawing performance of the entire OS was shown instead of just my app, but your mileage may vary.

Bypassing the Trouble Caused by Updating an iPhone App Provisioning Profile

[UPDATE] After many discussions on Twitter and many recommendations by different folks, I think that we have determined that the method outlined below is not necessary.  Mike Taylor has hit upon what appears to be a foolproof method for getting around the trouble caused by updating an iPhone app provisioning profile, and best of all, he did it in 140 characters:

@kalperin @MrRooni Delete old profile from Organizer. Download new profile ‘n drag to organizer. Restart Xcode. Choose new profile in target

Many thanks to Mike for helping me out here, I owe you a beer at WWDC10.  For those of you interested in the more masochistic way to get around the issues, feel free to continue reading:

A note before I begin: Everything below was done with the final build of the iPhone OS 3.0 SDK and I was building an app using the 2.2.1 frameworks.

I recently acquired a new iPod touch to use a development device.  One of the first things that I wanted to do was get my existing project up and running on the device so I headed over to the iPhone Development Program Portal to update my provisioning profile.

After adding the new device to my app’s provisioning profile I downloaded the updated profile and installed it into Xcode and onto the device via the Organizer.  So far so good, everything up until this point worked exactly as I expected it to.

Switching back to my project I changed my build settings to be a Release build under 2.2.1 on the device.  The app built fine, but I got an error when it tried to install the app onto the device, something error akin to “This device doesn’t contain the provisioning profile with which this app was built”.  Thinking that maybe Xcode just hadn’t seen the new profile yet I cleaned all targets in my project, restarted Xcode and tried again.  No dice, same error as before.

I then proceeded to delete all versions of the profile from the organizer and re-installed the new one.  My assumption was that once Xcode saw that the old profile didn’t exists anymore it would switch over and use the new one.  I cleaned all targets and built again.  This time I was treated to a different error: ”Code Sign error: Provisioning profile ’3E6AA725-6534-46F8-B9CE-D19AC9FD854B’ can’t be found”

After a bit of Googling I discovered that Xcode stores the ID of the provisioning profile in its project.pbxproj file.  This discovery led me to the fix:

  1. Close your Xcode project
  2. Navigate to your project folder in the Finder
  3. Right click on your .xcodeproj file and ‘Show Package Contents’
  4. Drag the project.pbxproj file to Xcode (or any plain text editor)
  5. Perform a search for the term ‘provision’ to find the PROVISIONING_PROFILE entry.
  6. Copy the existing profile ID and paste it into the find field of a find and a replace dialog.
  7. Open up the Organizer window (Window menu > Organizer) and navigate to your new profile under IPHONE DEVELOPMENT > Provisioning Profiles
  8. Click on your provisioning profile and copy its Profile Identifier
  9. Paste the string into the replace field in your open find and replace dialog.
  10. Replace all instances of the identifier, save the file, close it, and reopen your Xcode project.
  11. That should do it, build and go to run your app on your new device.

Now there is a great possibility that I am going WAY overboard here and missing a very obvious way to accomplish the same solution.  If that’s the case please let me know in the comments.

stevenf.com: How To Report a Bug

Steven Frank (of Panic fame) has posted a great article on his site: How to report a bug in a Mac OS X application

Here’s the teaser:

Bugs happen. It’s a fact of life. Although you may not be in the mood at the exact moment they strike, the best possible thing you can do is file a bug report with the developer. You may not get an immediate solution, but you will provide extremely valuable forensic information that should help the developer fix the problem over the long term. Here’s how to report a bug effectively.

Developers hate having bugs discovered by their users, but hate getting lousy bug reports even more. I’m tempted to include a variant of this article in the Help section of my next app under the heading, What should I do if I think I’ve found a bug?

Finding Memory Leaks With The LLVM/Clang Static Analyzer

 

While you may be familiar with using tools like Instruments to find and fix memory leaks in your application, the Clang Static Analyzer takes a different approach to memory leak detection by compiling your Xcode project and scanning each method, class, loop, and logic block for potential leaks. You may have heard of the Clang Static Analyzer referred to by the name of the command line tool used to run the analyzer: scan-build. That is how I will be referring to it for the remainder of this post.

Requirements & Where To Get It

scan-build is currently only available in binary form for OS X 10.5.
If you haven’t yet downloaded scan-build head on over to the LLVM/Clang Static Analyzer homepage and look for the Download section at the bottom of the page. Click the link for checker-NN.tar.gz (where NN is some build number). At the time of this writing the link reads checker-72.tar.gz. The developers of scan-build are very active so I have no doubt that the build number is already different.

Installation

Since scan-build is a command line tool it makes sense to install it into one of OS X’s pre-defined command line tool locations. We’ll put it in /usr/local/bin.

  1. Make sure that you’ve expanded checker-NN.tar.gz to your Downloads folder
  2. We’re going to be installing the checker binaries into your /usr/local/bin directory.  Run the following command to ensure that this directory exists:
  3.  sudo mkdir -p /usr/local/bin
  4. Open Terminal.app and move the contents of checker-NN to the /usr/local/bin directory (remember to replace NN with the build number of your download):
    sudo mv ~/Downloads/checker-NN/* /usr/local/bin/

Basic Usage

scan-build tests your code by compiling your Xcode project and studying it for defects during the build process. To check your code, you just invoke scan-build from the command line at the top level of any one of your project directories.

  1. Still in Terminal.app, change into one of your Xcode project directories
  2. Run scan-build on your Xcode project:
  3. scan-build xcodebuild

    There’s quite a bit of output when scan-build runs, but once it finishes running you will either see

    ** BUILD SUCCEEDED **
    scan-build: No bugs found.

    or something similar to

    ** BUILD SUCCEEDED **
    
    scan-build: 7 bugs found.
    
    scan-build: Open '/tmp/scan-build-fw1RAD/2008-07-31-1/index.html' to examine bug reports.
  4. Copy the section similar to Open ‘/tmp/scan-build-fw1RAD/2008-07-31-1/index.html’, paste it back onto the command line and hit return.
  5. You’ll be presented with the Summary screen. Click on the View link next to each bug to see your code with an inset bubble describing the bug that scan-build found

iPhone Usage

Using scan-build with the iPhone requires a little extra tweaking in your Xcode project settings to make sure that you are compiling your project using an SDK that is compatible with scan-build’s compiler.  The rest of these instructions assume a project who’s configuration has not been modified beyond what is provided when you create a new project.  I will be working with a project titled WhatsMyIP.

  1. Open the iPhone Xcode project that you want to run scan-build on and bring up the project settings panel.
    Open Project Settings
  2. On the General tab change the Base SDK for All Configurations to one of the Simulator SDKs.
    Project Settings - General
  3. Switch over to the Build tab and scroll down to the Code Signing section.  Change both the Code Signing Identity and the entry under it to Don’t Code Sign.
    projectsettings-build
  4. After making these changes you should be able to run scan-build on your iPhone project successfully.

Customizing Your Output

After running scan-build a few times the first thing that you might want to do is tell scan-build to put its reports in a different directory. To do that, simply specify the output folder on the command line like so:
scan-build -o /path/to/the/directory/where/you/want/your/report xcodebuild

There are a few other flags that can be passed to scan-build, but for now the reports that are generated should be the same regardless of the flags you set. Check out the Other Options section on the Static Analyzer usage page for the full (but still pretty short) list of available options.

Wrap Up

One thing to note is that scan-build is still in pre-1.0 and has some rough edges. You may notice some false-positives or other undesirable behavior. As with any pre-release software use it at your own risk and always have a backup of your work. That being said, I have not had nor heard of any disastrous problems with it, so your risk is probably pretty low.

A lot of folks in the OS X development community have gotten a lot of use out of scan-build in the past few months. One of the larger scale uses of it can be found on the Adium project, you can view the results of their static analysis here.

Good luck!