tags:

views:

352

answers:

4

Hi,

What's the correct way to resign the current firstResponder?

I've seen the following: Looping through fields and calling resignFirstResponder on each.

[[self textFieldForRow:0] resignFirstResponder];
[[self textFieldForRow:1] resignFirstResponder];
[[self textFieldForRow:2] resignFirstResponder];
[[self textFieldForRow:3] resignFirstResponder];

And this which looks like it's calling a private function, is this app store safe?:

UIWindow *keyWindow = [[UIApplication sharedApplication] keyWindow];
UIView   *firstResponder = [keyWindow performSelector:@selector(firstResponder)];   
[firstResponder resignFirstResponder];      

Is there a better way?

Thanks!

Comments: Looks like the second method is using a private api and someone's app has been rejected because of it: link

A: 

The code you have up there is not calling any private function. What is happening is:

 //Gets the application window
 UIWindow *keyWindow = [[UIApplication sharedApplication] keyWindow];
 //Gets the first Responder View for the window
UIView   *firstResponder = [keyWindow performSelector:@selector(firstResponder)];  
//Make the UView resign the first responder 
[firstResponder resignFirstResponder];     

All of those are public functions, so you will not have any problem with the app store as far as I know.

Additionally is there a better way to do what exactly?. If you are talking about getting the UIView that is the firstResponder to the keyWindow, you could do when creating your uiview:

myView.tag = 100;

and to get it:

UIView *firstResponder = [self viewWithTag:100];
OscarMk
I don't see "firstResponder" defined as a property or a method in the UIWindow documentation?
Hua-Ying
UIWindow->UIView->UIResponder->isFirstResponder (that's the inheritance chain leading to the method). Don't forget to look at superclass methods...
Kendall Helmstetter Gelner
You are correct it is not defined as a method in the UIWindow documentation, but it is defined in UIResponder (inherited)
OscarMk
isFirstResponder is: - (BOOL)isFirstResponder, firstResponder is completely different and NOT a BOOL. There it a firstResponder variable in the UIWindow.h header but it is defined as private: UIResponder *_firstResponder;
Hua-Ying
Is that code actually working for you?. I am thinking maybe firstResponder is just a custom method. I did just see that variable declared in UIWindow.h, but there is no accessor for it.
OscarMk
Yes it works but it doesn't mean it'll pass the app store approval process. A variable that starts with a _ usually means it is a private variable not meant to be used outside the class.
Hua-Ying
A: 

My suggestion would be to implement a hacky & slow version of firstResponder yourself in a category and then file a radar requesting they add the method. Something along these lines:

- (id)my_FirstResponder
    for view in [self subviews]
        if [self isFirstResponder]
            return self
        return [self my_firstResponder]
    return nil

Using performSelector: to invoke a method not in the public headers is definitely grounds for rejection, so don't do that. Oh, and don't forget to use a prefix (like the above code does) when adding a category to avoid conflicts.

Colin Barrett
+2  A: 

Have a look at this question: How do I [legally] get the current first responder on the screen on an iPhone?

My answer to that question should work perfectly in your situation.

Thomas Müller
Thanks, That's a great solution!
Hua-Ying