Resign first responder in didSelectRowAtIndexPath when using UINavigationController - ios

I want to resign first responder from the currently edited textfield when a row is selected in the UITableView and a push segue is triggered inside a navigation controller. This is happening within a popover.
I've tried two things:
(1) I can see that the textfield is resigning the first responder while animating, but then when I go back to the view controller it takes first responder again and shows the keyboard.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[self.view endEditing:YES];
}
(2) This will prevent the restoring of the editing when going back to the view controller, but this method breaks the animation. In the end of the animation, the first view controller gets black and it jumps a little bit.
EDIT: Just realized that this is only visible in landscape mode as it has something to do with that the keyboard animates faster than the push animation, and it gets black as soon as the keyboard is gone and the popover starts to animate to a higher height when the keyboard leaves room for it. The animation can't handle expanding the popover while animating the push animation in the navigation controller. When removing the code below and pushing and letting iOS remove the keyboard, the keyboard and push animation is taken exactly the same time and avoiding this issue. I wonder how I can make that happen myself while forcing the resignation.
- (NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[self.view endEditing:YES];
return indexPath;
}
How can I resign first responder when changing view controller without it restoring the first responder on the text field again when navigating back?

Hold on a minute. So the issue is that when you perform the segue (and dismiss the view) when the view restores it has a sort of shadow of the keyboard showing. Is that it? In that case. You could try the following. when you click the tableviewcell. Do a check. like the following.
if(firstResponder != nil){
//register for keyboard hide notification
[[NSSnotificationCenter defaultCenter] addObserver:self selector:#selector(keyboardDidHide:) name:#"UIKeyboardDidHideNotification" object:nil];.
[firstResponder resignFirstResponder];
} else {
[self performSegue:#"yoursegueidentifier" withSender:nil];
}
That will only launch the segue if there is not a responder (and hence, not a keyboard). If there is a keyboard, it registers for the keyboard hide notification, and then resigns the responder. Then, in the method that responde to the keyboard hiding
- (void)keyboardDidHide:(NSNotification *)notification {
[self performSegue:#"yoursegueidentifier" withSender:nil];
}
This should only perform the segue when the keyboard has hidden, so it should resolve the animation issue. You may need to modify your storyboard to have the segue launch from the view controller and not from the cell's button, I'm not sure about how your architecture is. let me know if this works or not.

Related

KeyBoard gets locked after popover dismissal

There are multiple textfields in a viewcontroller in which some of them are customised (one tapping those textfield will launch a popover controller, from that user can select the option which will get displayed in tapped textfield).
I have a tap gesture on the view controller for dismissing the keyboard (if it's on the screen).
Keypad gets locked(if it's visible) when I open the popover controller on taping the customised textfield. The keyboard is not getting dismissed even if I tap on the parent view or else on the dismiss button in the keypad.
I have tried this 2 snippets to hide the keyboard, but it's not working
[self.scrollView endEditing:YES];
[[[UIApplication sharedApplication] keyWindow] endEditing:YES];
You can use textfields delegate to prevent it from presenting a keyboard and instead present popover yourself by implementing this textFieldShouldBeginEditing method
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField {
if(textField == myCustomTextField) {
[self openCustomPopover];
return NO;
}
return YES;
}
more on its delegate methods here https://developer.apple.com/library/ios/documentation/UIKit/Reference/UITextFieldDelegate_Protocol/index.html#//apple_ref/occ/intfm/UITextFieldDelegate/textFieldShouldBeginEditing:

searchBarTextDidBeginEditing delegate method called again on back button click

I am developing iPhone app in which i got stuck at one point.
I have one viewController with navigation bar hidden and search bar is in the centre of the page.
when user clicks on searchBar searchBarTextDidBeginEditing method gets fired.
after this on text change of searchBar textDidChange method i am loading live data in tableview and on click of tableview i am navigating to other page with navigation bar non hidden.
Now when i press back button again i comes to search page here searchBarTextDidBeginEditing method again gets fired.
Why this method gets called again on back press ?
Please help and thanks in advance.
Your SearcBarTextDidBeginEditing called due to your search display controller still in Active mode,
In your TableView Delegate Method,
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
[self.view endEditing:YES];
[self.searchDisplayController.searchBar resignFirstResponder];
// Set Navigation
}
And In Same Class , In View Will Appear SET,
-(void)viewWillAppear:(BOOL)animated{
self.searchDisplayController.Active = NO;
}
Hope this will help you!
I think the UITextField keeps the focus on itself when you navigate.
Try [textField resignFirstResponder] when you click on your tableView to navigate.

No longer able to hide keyboard during viewWillDisappear in iOS7

The following code used to work in iOS6 to hide the keyboard when a view controller was popped off of the navigation stack:
- (void)viewWillDisappear:(BOOL)animated {
[self.view endEditing:YES];
[super viewWillDisappear:animated];
}
However, in iOS7, the [self.view endEditing:YES] line seems to get ignored. I tried the command in other view events (viewDidDisappear, viewWillAppear, and viewDidAppear), and the only one it worked in is viewDidAppear. It seems that once a "pop" is initiated, we lose the ability to hide the keyboard until the view controller is "pushed" back on the stack.
While placing the code in viewDidAppear does work to hide the keyboard, the bad thing is that the keyboard is displayed briefly when the viewController is pushed back on to the navigation stack...pretty unacceptable from a UI perspective.
Has anyone else had success in working around this issue? I would prefer not to have to write my own CANCEL button, but right now, that is the only thing I can think of that will work.
If it's a UITextView set the editable property to NO. I tried this and it hides the keyboard as soon as it's set. I haven't tried it with a UITextField but I'm guessing you'd get the same result with setting the enabled property to NO. If that doesn't work, create a UITextField with userInteractionEnabled set to NO as a background for a transparent UITextView and use the editable property as stated above.
There was a change in iOS 7 where view controllers that are presented as modal forms cannot dismiss the keyboard by default. To fix this, you need to override your view controller's disablesAutomaticKeyboardDismissal method and return NO.
The problem is that somewhere between the time I press the "BACK" button and the time that viewWillDisappear fires, the current text field's canResignFirstResponder is getting set to FALSE, which is preventing the keyboard from hiding. I have not been able to discover anything in my code which could cause this, and I strongly suspect that it could be some kind of iOS 7 bug, as the same code worked for me under iOS 6.
As a workaround, I implemented the following solution. I subclassed UINavigationController and overrode the following method:
- (UIViewController *)popViewControllerAnimated:(BOOL)animated {
[self.topViewController.view endEditing:YES];
return [super popViewControllerAnimated:animated];
}
This caused the keyboard to appropriately disappear when I tapped the Back button to pop the current view controller. Nice sigh of relief that I didn't have to write a bunch of custom Back buttons.
To hide the keyboard when the text field lost focus
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField
{
if ([textField isFirstResponder])
[textField resignFirstResponder];
return YES;
}
I tried a workaround. It may not be what you guys are expecting.
If you are using storyboard, You can resign the keyboard in "prepareForSeuge" method.
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
[self.view endEditing:YES];
}
It worked fine for me.
Approach given in the below will definitely hide the status bar in iOS7.
- (BOOL)prefersStatusBarHidden
{
return YES;
}
Add this to your .plist file (go to 'info' in your application settings)
View controller-based status bar appearance --- NO
Then you can call this line to hide the status bar:
[[UIApplication sharedApplication] setStatusBarHidden:YES];
In case your app is developed to support iPhone only, status bar won't hide when you run your app in iPad.
Put your UItextfield or UItextview for global declaration.
UITextfield textfield = your textfield object;
-(void)viewWillDisappear:(BOOL)animated
{
[self.view endEditing:YES];
[textfield resignFirstResponder];
[super viewWillDisappear:animated];
}

Dismissing Keyboard FirstResponder problems

So i am making an app and am having some problems with dismissing the keyboard from UISearchBar and UITextFields. Here is the structure of my app:
NavigationController -> ViewC1 - (Modally)-> ViewC2 -(Modally) -> ViewC3
I have a search box in ViewC1, and when the "Search" button on the keyboard is pressed the keyboard is dismissed, this works fine. However if i return to ViewC1 after being in ViewC3 the keyboard no longer dismisses when the "Search" button is pressed. In the search bar delegate method i have put as follows:
- (void) searchBarSearchButtonClicked:(UISearchBar *)search
{
if ([search isFirstResponder]) {
[search resignFirstResponder];
} else {
[search becomeFirstResponder];
[search resignFirstResponder];
}
}
This does not solve the problem and i am not sure why the keyboard is not dismissing. For reference, when returning to the original ViewC1, ViewC3 is dismissed as follows:
UIViewController *parent = self.presentingViewController;
[parent.presentingViewController dismissViewControllerAnimated:YES completion:nil];
Any help is appreciated, thanks.
Okay i figured out what the problem was. They first responder was being resigned but the keyboard was not disappearing because of a focus issue. There is a default behaviour on modal views to not dismiss the keyboard (which is not a bug apparently). So after returning from the modal view it was still having this behaviour (resigning first responder but not dismissing keyboard). The way i solved this was by placing the following code in both the modal views .m files:
- (BOOL)disablesAutomaticKeyboardDismissal {
return NO;
}
This solved it for me. Then by either using:
[search resignFirstResponder];
or
[self.view endEditing: YES];
The keyboard will dismiss fine!
You'll need to do some debugging with break points to figure out why that conditional statement is not being hit. You could also use the endEditing method in UIView to simply resign the responder whenever search is clicked:
- (void) searchBarSearchButtonClicked:(UISearchBar *)search
[search endEditing:YES];
}
http://developer.apple.com/library/ios/#documentation/UIKit/Reference/UIView_Class/UIView/UIView.html
Try it....
- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar
{
[mySearchBar resignFirstResponder];
}
Please declare IBOutlet UISearchBar *mySearchBar; in your .h file
Set delegate in your .xib file.
Hope this helped
(A year later..)
I've just had the same problem with my iPad app.
I had a"Please register" UIView containing a few UITextFields which I would pop onto the screen. When the user tapped on a Close button, it'd disappear, and I'd use removeFromParentViewController to get rid of it.
[self.pleaseRegisterDlg removeFromParentViewController];
Now, when I ran this code on a real device in debugging mode from XCode, the story ended there. It all worked fine. But when I built an In-House app with this code, it behaved differently.
I would find that sometimes, no matter how many resignFirstResponders or disablesAutomaticKeyboardDismissals I put into the code, there would be times when the onscreen keyboard would suddenly appear, and refuse to go away programatically.
It made no sense, as the rest of my app didn't have any UITextFields... there was no reason for the app to display a keyboard.
My solution was to set the "Please Register" UIView to nil after removing it from the parent view.
[self.pleaseRegisterDlg removeFromParentViewController];
pleaseRegisterDlg = nil;
Apparently, having a UIView which isn't actually attached to any other UIViews but which contains UITextFields is sometimes enough to confuse iOS, and make the onscreen keyboard appear.
(Sigh. This one line of code wasted a few hours of my afternoon.. lesson learned !)

iOS - Create an Popover View using StoryBoard

Hi there, Now I'm trying to create a Pop-OverView using an Xcode
storyboard. Firstly, I have
rootViewController, UIViewController, and UITableViewController
I want the UIView to act as a page flip and the UITableView will show popOver under the navigationBar item controller.
For the UITableView, I want to make a Pop-Over under NavigationBar controller. The problem is, when I touch the Navigation item to show the UITableViewController, it shows correctly, but when I try to close the Pop-Over View, it won't close. And then, the navigation item doesn't work well. It shows multiple instances of popOverView when I touch it multiple times.
This doesn't seem to make sense to me. Can anyone help me out or tell me where to find documentation / tutorials on this?
UPDATE:
For the UIPopOverController, it seems to work well now, but it is still bugging me when I touch a Navigation Item multiple times. It will show multiple instances of PopOver. How can I handle it, so it will show only one instance?
I had the same problem and mostly found the solution here. Basically you change the action of the button each time it's pressed to either display or dismiss the popover. Here's the code I ended up with:
#interface FilterTableViewController : UITableViewController {
UIPopoverController *editPopover;
id saveEditSender;
id saveEditTarget;
SEL saveEditAction;
}
-(void)prepareForSegue:(UIStoryboardPopoverSegue *)segue sender:(id)sender{
if([[segue identifier] isEqualToString:#"EditFilterSegue"]){
// Save the edit button's info so we can restore it
saveEditAction = [sender action];
saveEditTarget = [sender target];
saveEditSender = sender;
// Change the edit button's target to us, and its action to dismiss the popover
[sender setAction:#selector(dismissPopover:)];
[sender setTarget:self];
// Save the popover controller and set ourselves as the its delegate so we can
// restore the button action when this popover is dismissed (this happens when the popover
// is dismissed by tapping outside the view, not by tapping the edit button again)
editPopover = [(UIStoryboardPopoverSegue *)segue popoverController];
editPopover.delegate = (id <UIPopoverControllerDelegate>)self;
}
}
-(void)dismissPopover:(id)sender
{
// Restore the buttons actions before we dismiss the popover
[saveEditSender setAction:saveEditAction];
[saveEditSender setTarget:saveEditTarget];
[editPopover dismissPopoverAnimated:YES];
}
-(BOOL)popoverControllerShouldDismissPopover:(UIPopoverController *)popoverController
{
// A tap occurred outside of the popover.
// Restore the button actions before its dismissed.
[saveEditSender setAction:saveEditAction];
[saveEditSender setTarget:saveEditTarget];
return YES;
}
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
// Before we navigate away from this view (the back button was pressed)
// remove the edit popover (if it exists).
[self dismissPopover:saveEditSender];
}

Resources