views:

48

answers:

2

I keep seeing examples that manually iterate through all of the subviews of a certain type in a UIView. For example, if you want a click outside of a keyboard to dismiss the keyboard regardless of which field is active, you might:

-(IBAction)backgroundClick:(id)sender
{
    [myTextField resignFirstResponder];
    [myOtherTextField resignFirstResponder];
    // ... repeat for each of my zillion text fields.
}

Instead of something like:

for(UIView *v in self.view.subviews)
    if(v.hasKeyboard) // or something like java's instanceof
        [v resignFirstResponder];

Although improvements to the specific case of the keyboard (such as discovering which one is first responder now) are appreciated, I'm more interested in the general case.

+2  A: 

Couldn't you do something like

if([v isMemberOfClass:[UITextField class]]){
[v resignFirstResponder];
}

?

Gubb
Thanks! I'll be able to use that in several places! For the text field editing specific case, I also eventually found that you can do [self.view endEditing:YES] instead of iterating.
Peter DeWeese
+3  A: 

Alternatively, you could iterate through the views with

if( [v respondsToSelector:@selector(isFirstResponder)] && [v isFirstResponder])
{
  [v resignFirstResponder];
  break;
}

This way will only call resignFirstResponder on the current first responder and will stop when the current first responder is found. It will work on UITextFields, UITextViews, etc as well as any future text editing views (assuming they continue to implement the responder methods).

For the more general case you can use

if( [v isKindOfClass:UITextField.class] )
{
  [v resignFirstResponder];
}

For generic keyboard dismissal the first is preferred, since all you are interested in is the keyboard. The object claims it will handle the message (method call), so you don't have to actually care what type it is. If you really need to be sure it is a UITextField the second option is preferred.

Peter