views:

40

answers:

1

Hi,

I'm having some difficulty understanding exactly how the responder chain works in an iPhone application.

My situation is as follows. I have two UIViewControllers that are installed on a tab bar controller. Call them view controller A and B. They are unrelated in the sense that neither of them has a reference or knows about the other.

Both A and B need to respond to remote control events (the play/pause/stop buttons). Controller A wants to respond to these events all the time, whereas B only wants to respond to them when the user selects a certain function. When my app starts, A becomes the first responder immediately and is able to receive the remote control events. When B wants to receive the events, it becomes first responder, and then begins to get the events instead of A.

The problem occurs when B is done using the remote control. At this point, B calls resignFirstResponder on itself. Thereafter, neither A nor B gets any remote control events.

I assumed that when B resigned first responder status, the thing that previously was the first responder would be restored. Is this not how it works?

If not, how do I restore A to first responder? Remember that A and B are separate tabs, so B doesn't have a reference to A or know that A is supposed to be the first responder. So I don't want to explicitly call becomeFirstResponder on A. What I need instead is a way to get the previous first responder and restore it (I think). I'm a bit puzzled as to why this doesn't just happen automatically.

Thanks, Frank

+1  A: 

The docs on UIResponder as well as the Event handling guide for iPhone OS indicate that the responder chain isn't exactly laid out how you expect it to be. It's not a linked chain of potential responders which can be tacked to and pulled from. Rather, it is directly associated with the view hierarchy currently presented to the user.

What this means is that when B resigns first responder, B's view controller (if there is one) or its superview becomes first responder, presuming is has implemented canBecomeFirstResponder:. If it can't, its view controller or superview becomes first responder, all the way up to the UIApplication.

If A and B are not in a hierarchy where one is a subview of the other, the responder chain will not return first responder to A when B resigns. Instead, B will resign first responder to its superview. What you most likely want to do is to implement becomeFirstResponder: in the view that is above both A and B. The method would simply hand first responder over to A. That way, B can grab first responder, and later, when it resigns it, the superview will hand it back to A.

Kalle
Thanks, I experimented with it some more and your explanation makes sense. It actually doesn't matter whether view B becomes first responder or not. As soon as I switch to its tab, view A stops being first responder and stops getting the remote control events.The common superview in my case is probably the tab bar controller's view. Do I have to subclass UITabBarController to do what I want?
Yes - subclassing UITabBarController appears to work. When nobody else is listening, the subclass gets the remote control events. Now all I have to do is figure out an elegant way to dispatch the event to the right place.
Call A's "becomeFirstResponder:" method to hand first responder to A. IIRC.
Kalle