views:

247

answers:

1

I have a rather popular Bonjour-based application in App Store. It works perfectly, but around 0.2% of my users report a bizarre bug: "no arrows appear on the edges of the screen, so I can't share stuff with other people!". Needless to say, displaying these arrows is tied to the browsing of a particular Bonjour service on the local domain.

The problem is, the Apple review team seems to intermittently happen to be in this 0.2%. This isn't good for review results, as you might imagine. No matter how much I try, I cannot reproduce this bug.

From the few logs I have, it looks like my app is running correctly, just not receiving NSNetServiceBrowser delegate calls. What can cause this?

Things I've tried:

  • Having a shorter service name < 14 chars in length to be in spec.
  • Publishing on @"local." rather than @"" (aka Go Look For The Default Registration Domain). My app is rather useless on a wide-area network anyway.

Things I haven't tried: restarting the browsing machinery periodically. (I have two browsers, though, one looking for the legacy longer name, one for the new shorter one.)

What to do?

A: 

There are many areas where things can go wrong. Since the NSNetService instance provided to your delegate methods is autoreleased, you need to retain it if you plan on reusing it out of scope for that method. Most people will add it to an NSMutableArray or NSMutableDictionary so that it is automatically retained, and only autoreleased when removed from the collection. If that is the case for your code, make sure that you have properly initialized your collection before adding the object. Since messages to nil are perfectly ok, you may be sending the addObject:netService message to nil. You will not receive an obvious indication that you never initialized your array or dictionary, and it will appear as though everything is working just fine…except that delegate messages “mysteriously” don’t fire off when peers change status, when you try to connect to one, etc. This crops up often enough in Bonjour troubleshooting that I would recommend it as the first place to start your troubleshooting. It happens to the best of us.

One easily missed problem for apps running network code on a background thread: throwing an un-handled exception on that thread. This can occur without crashing your whole app due to Cocoa/Unix’s rules on threading. If your networking code “just stops working for no reason,” then you may want to check your iPhones Console and logs for error messages. Make sure you have set a breakpoint on the objc_exception_throw symbol.

For more, read the full article "Troubleshooting Bonjour Networking for the iPhone" at my dev blog.

Zack
The NSNetService is properly memory-managed, alive, and running on the main thread, scheduled correctly on the NSRunLoop. (Thanks for the link!)
millenomi
Two thoughts. Have you written an error handler for name collisions in your netService:didNotPublish: method, or are you using publishWithOptions: along with NSNetServiceNoAutoRename, instead of plain ol’ publish, to disable the automatic renaming? Also, it is more and more common for public hot spots to prevent peers from directly communicating with each other on the local domain by "isolating" them (similar to PVLAN edge ports on a switch). Many cheap devices have this option. There is no way around it, other than handling it gracefully. This may be what the Apple testers are checking for.
Zack