1

I'm using TPKeyboardAvoiding in my app to hide move text fields when the keyboard is showing, but I'm getting an exception when I try to end editing the text field. It's coming from this method in TPKeyboardAvoiding:

- (void) touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
    UIView* view =[self TPKeyboardAvoiding_findFirstResponderBeneathView:self];
    NSLog(@"%@",[view description]);
    [view resignFirstResponder]; //this line gives the exception
    [super touchesEnded:touches withEvent:event];
}

I'm a bit confused here. Shouldn't all UIViews respond to resignFirstResponder? Thanks for the help.

Full error:

2014-03-25 17:40:39.919 Rysk[5553:70b] -[MenuViewController textFieldDidBeginEditing:]: unrecognized selector sent to instance 0xb63c820
Connor Pearson
  • 63,902
  • 28
  • 145
  • 142
  • Try this instead: `[self.view endEditing:YES];` – klcjr89 Mar 25 '14 at 03:11
  • Try `if ([view isKindOfClass:[UITextField class]] || [view isKindOfClass:[UITextView class]]) {[view resignFirstResponder]; }` – Akhilrajtr Mar 25 '14 at 03:12
  • @troop231 I'm getting an exception on that too – Connor Pearson Mar 25 '14 at 03:13
  • How about `[view endEditing:YES];` – klcjr89 Mar 25 '14 at 03:15
  • I got an exception on that as well – Connor Pearson Mar 25 '14 at 03:19
  • resignFirstResponder can be called on objects which are subclasses of UIResponder (UIView for example). you better check if you're calling this on appropriate object. do a NSLog and print the object view to see. – nsuinteger Mar 26 '14 at 06:32
  • @nsuinteger, your guess is correct to NSLog the object but if you will go with the TPKeyboardAvoid class you will see it check for UITextField and UITextView's only. I think it will not give go ahead. but lets see. – NeverHopeless Mar 26 '14 at 07:10
  • if you want to simply avoid the exception then use this, put an else block & print the object so you will know when it wont work but will not give exception `if ([view respondsToSelector:@selector(resignFirstResponder)] ) { [view resignFirstResponder]; }` – nsuinteger Mar 26 '14 at 07:14

4 Answers4

1

Not sure if you have called [yourTextField resignFirstResponder] as well. So it is possible that the UITextField (in the code you have provided) is not the FirstResponder at that point. I would suggest to adjust your code like this:

- (void) touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
    UIView* view =[self TPKeyboardAvoiding_findFirstResponderBeneathView:self];

    if([view conformsToProtocol:@protocol(UITextFieldDelegate)] || [view conformsToProtocol:@protocol(UITextViewDelegate)]) && 
       [view isFirstResponder] && [view canResignFirstResponder])
    {
       [view resignFirstResponder];  
    }

    [super touchesEnded:touches withEvent:event];
}

Also, if you using PODs please make sure you are using a latest version, because the one i am using has something like this in this event:

- (void) touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
    [[self TPKeyboardAvoiding_findFirstResponderBeneathView:self] resignFirstResponder];
    [super touchesEnded:touches withEvent:event];
}

Hope it helps!

NeverHopeless
  • 11,077
  • 4
  • 35
  • 56
  • Thanks for your answer. I'm still getting an unrecognized selector error on that line though. My code used to be like that as well, I've changed it a bit trying to find where the error was. – Connor Pearson Mar 25 '14 at 13:28
  • Do you resign by yourself too ? I mean outside this class ? check my updates as well – NeverHopeless Mar 25 '14 at 13:46
  • I still get the same exception checking if it can resignFirstResponder. The only places resignFirstResponder is called is inside that class – Connor Pearson Mar 25 '14 at 23:42
  • Do you get this exception on a single screen or at application level ? Can you post the complete error messsage? I guess it also tells which selector is unrecognized and in which controller. – NeverHopeless Mar 26 '14 at 05:47
0

Update your code as follows:

- (void) touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
    UIView* view =[self TPKeyboardAvoiding_findFirstResponderBeneathView:self];
    NSLog(@"%@",[view description]);
    if([view isKindOfClass:[UITextField class]]) {
        UITextField *myTextField = (UITextField *)view;
        [myTextField resignFirstResponder];
    }
    [super touchesEnded:touches withEvent:event];
}
Sujith Thankachan
  • 3,508
  • 2
  • 20
  • 25
0

Try this simple method....

- (void)viewDidLoad
{
    [super viewDidLoad];

    //--Gesture to resign keyborad on touch outside
    UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(dismissKeyboard)];
    tap.cancelsTouchesInView = NO;
    [self.view addGestureRecognizer:tap];
}


//-- Resign keyboard on touch UIView
-(void)dismissKeyboard
{
    self.view.frame = CGRectMake(self.view.frame.origin.x, 0, self.view.frame.size.width, self.view.frame.size.height);
    [self.view endEditing:YES];
}
Rajesh Loganathan
  • 11,129
  • 4
  • 78
  • 90
0

I solved the problem by having my view controller than contains the TPKeyboardAvoidingScrollView implement the UITextFieldDelegate protocol. Most importantly, these two methods:

- (void)textFieldDidBeginEditing:(UITextField *)textField{}
- (void)textFieldDidEndEditing:(UITextField *)textField{}
Connor Pearson
  • 63,902
  • 28
  • 145
  • 142