views:

164

answers:

2

I am developing a game that uses a different controller for each level. It needs to detect a shake via the accelerometer, so it registers itself as a delegate like so:

UIAccelerometer *accel = [UIAccelerometer sharedAccelerometer];
accel.delegate = self;
accel.updateInterval = kUpdateInterval;

When the level ends, this controller gets dealloc'd and freed. Previously, I was getting a crash after this controller was freed because I didn't nil out the delegate on UIAccelerometer (i.e. it was still sending events to an object that has now been freed). So now, inside of dealloc, I'm doing this:

UIAccelerometer *accel = [UIAccelerometer sharedAccelerometer];
accel.delegate = nil;

All is well and good and the first level plays without a hitch. The problem happens when I get to the next level, create a new level controller and run that first batch of code again (setting the new contoller now as the delegate). After this, I'm not getting any calls from the Accelerometer.

So the question is, are you only allowed to have one delegate per app for the Accelerometer, or am I just missing something? I haven't seen anything in the docs that disallows setting the delegate multiple times. I'm slightly new to Obj-C, but as far as I understand delegates this shouldn't be too unorthodox.

Note: I know that in 3.0 I could just listen for shake notifications. Unfortunately, I need something else to be first responder the entire time I'm interested in the shake. So I can't just refactor to that option.

+1  A: 

In general, objects that have delegates have only one at a time. Unless otherwise documented, there shouldn't be any limitations on setting more than one different object as delegate over the lifetime of a particular instance.

I wonder if what's happening is that your first controller is being dealloced after you set the second controller as the accelerator delegate. Have you watched that code with the debugger to be sure that everything's happening in the order you expect?

Sixten Otto
+1 Good point. I'm going to test that now and will report back.
Bdebeez
Yep, that did it. The controller was being released (down to 0) but wasn't immediately dealloc'd. As such, it didn't nil out the property until after the 2nd controller was created.Thanks!
Bdebeez
+1  A: 

A possible solution would be to have a different class, perhaps your app delegate, act as the delegate of the UIAccelerometer and have that class send custom a NSNotification when it receives the accelerometer:didAccelerate: message. You could either only send the message when you detect the type of acceleration you care about or you could send the notification every time and include the UIAcceleration paramter as part of the notifications userInfo. Your controllers that are interested in acceleration data can register for the notifications as needed.

Jason Jenkins
I had thought about the option of AppDelegate, but hadn't thought of doing it via notification - thats a great idea, thanks :) I'm hoping I don't need to do that, but if necessary that's a doable workaround.
Bdebeez