I had issue that every time when I enter a view controller - which is the "MessageListViewController" in the following screen-shot, the keyboard will be automatically popped out.
The thing is I used a UITextView in this MessageListViewController for text input, and when I pop this view controller from navigationController stack, if I leave the keyboard open, then the next time when it was pushed again, this keyboard will be popped out automatically.
If I make the text view resignFirstResponder before I popped out this view controller, then the next time enter it will be fine. However resignFirstResponder manually will make the keyboard dismissing with an ugly animation (manually dismiss keyboard it will make the keyboard always go downing the screen vertically, however the view controller popping transaction is horizontal, so it will look very wired)
I tried to build a simple sample to test the keyboard dismiss behavior - there are two view controllers, one is the rootViewController of the navigationController, and it will push another into the viewController stack, so the pushed view controller contains a UITextView, if I highlight the text view of the pushed one, then go back to the root view controller, the animation works just fine, also the keyboard won't be automatically popped out. So I just don't know why in my project, this keyboard always shows up unexpectedly if I just left the page without manually dismiss the keyboard.
BTW, the following call stack happened between viewWillAppear and viewDidAppear. It looks like triggered by iOS to restore the last state of the UITextView.
- (UIView*)findFirstResponder {
if (self.isFirstResponder) {
return self;
}
for (UIView* subview in self.subviews) {
UIView* ret = [subview findFirstResponder];
if (ret) {
return ret;
}
}
return nil;
}
NSLog(#"%#", [[[UIApplication sharedApplication] keyWindow] findFirstResponder]);
I also tried to track with the key window's first responder when this call stack triggered by keyboard will show notification, and the out put is just "nil".
Thanks guys for helping, I just realized where the problem is, actually I did not declare that the messagelistViewController which I used here is actually a singleton, so it never release even I pop the this out of the viewController stack.
Under that scenario, when the next time this view controller was appear again, the UIKit will be smart enough to restore the previous view state if it's not dealloced.
And in my test sample, I did not keep the test viewcontroller when it was popped out of stack.
so that's why this works fine for my test sample.
Then my final solution is kinda simple, just remove the textview from it's superview when the view did disappear, and then re-add this back when the view will appear.
It turns out my question is a little bit stupid, however it do let me know two things:
1) The view controller will restore to it's previous state every time when it appears if you not delete it
2) The keyboard dismiss animation will always be going down if manually resign the input from the first responder, if we don't want this effect, we shall never dismiss it manually.
I created a demo in iOS 7 as per you said in your question, it was working fine for me even I didn't have to call resignFirstResponder method for resigning keyboard. So you could look in your code as you might have been calling becomeFirstResponder somewhere making the keyboard to be active again or simply post your code here so I could have a look at it.
Related
I know that the view controller must be firstResponder in order for the inputAccessory to stay at the bottom. I am using a custom inputView / keyboard. I can manually dismiss it with a done button by removing the inputView but not resigning first responder. However when I enable the interactive drag to dismiss on my scrollview, the code automatically resigns first responder. So how can I use the interactive drag to dismiss and yet keep my viewcontroller as first responder? Anyone done this before? I thought maybe it is not possible and that I may need to make my own interactive drag to dismiss using a gesture recognizer.
More info:
I have a button that swaps between standard keyboard and my custom one. I have seen dismissing these cause 2 keyboard did dismiss notifications. I thought I could become firstResponder in the keyboardDidHide method but this didn't work well since I couldn't tell the difference between when I manually dismissed the keyboard and when the interactive drag does it. This matters because I don't need to reload the input view or become first responder when I manually dismiss because I took care of it already.
Any suggestions would be amazing. I am trying to use inputView and inputAccessoryView on the UIViewController level.
Well after a day of pulling my hair, I have an answer.
Using the canResignFirstResponder of my viewcontroller did the trick. In viewWillAppear I set a BOOL responderOverride = YES;
In viewWillDisappear I call
responderOverride = NO;
[self resignFirstResponder];
When the interactive drag on the scrollview tries to resignFirstResponder, canResignFirstResponder returns no which prevents my viewcontroller from resigning and keeps my input accessory retained and sitting at the bottom of the screen.
There is a lot of other code with reloading input views but since the real question was how to force a controller to stay first responder so we don't lose our input accessory view, then this solution works.
override var canBecomeFirstResponder : Bool {
get {
retrun true
}
}
This works for me
I want the keyboard to slide up as the view controller slides up. But for one of my view controllers that I present modally, the keyboard appears instantly when the view controller is presented, so the keyboard appears then the view controller slides up from under it, causing an ugly effect.
Oddly enough, this instantaneous behaviour happens when it's in viewDidLoad, but having it there works fine for another view controller. (But in the instantaneous one it appears for a UITextField, while the proper one is for a UITextView.)
Here's what the code looks like:
- (void)viewDidLoad
{
[super viewDidLoad];
[self.URLTextField becomeFirstResponder];
}
How do I make it present alongside the view controller? I don't have to do an ugly dispatch_after do I?
If it's loading too quickly with some methods (ViewDidLoad/ViewWillAppear) and too slowly with others you could try doing something in the middle.
I wouldn't suggest it as I'm sure theres a way to have it do what you like but I imagine that in viewDidLoad you can set the view up to respond to to keyboardWillShow and then become first responder and in the notification delay for a few milliseconds
Yes, I struggled a bit with that title...
Here's what my setup is meant to do:
I push a viewController (resultViewController) onto the navigation stack. Immediately (literally in the next line of code) I present another viewController to the rootViewController (filterViewController).
So far, so good, and things work as expected.
The modally presented viewController contains a tableView. Selecting a cell is supposed to present another viewController in the current (filterView) controller.
[self presentViewController:filterDetailsController animated:YES completion:^(void){
}];
This is where things go awry: The above snippets is called at the correct time, but the viewController does not appear until I perform an additional tap or gesture somewhere in the filterView. This suggest that the stacking of modalView inside modalView somehow messes things up. If I change the animated parameter to NO, the viewController is presented immediately.
An obvious work-around would be to set animated to NO and perform a manual animation in the completion block. I would however love to see if anyone have come across anything similar and knows how to fix the problem.
I'm having a weird issue with a navigation controller's back button animation:
my app has a tab bar control with 3 tabs, one of them has a navigation controller with two subsequent view controllers, the first one just show a master table and the second one details, the problem comes when I tap the back button from the detail view controller, instead of slide back to the master view controller it just pops the view without animation.
I've noticed that if I first go to another tab, and then return again to this one, the animation will trigger normally.
I've rebuilt the whole app navigation from scratch but the problem still persist, any help is appreciated.
Thanks in advance!.
Edit: More info added
This is how my storyboard looks like in that particular branch:
Here's the prepareForSegue from "Partidos Activos" view controller:
#pragma mark - Segues
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
if ([segue.identifier isEqualToString:#"PartidosEnDia"]) {
PartidosActivosEnFecha *paf = segue.destinationViewController;
CalendarCell *senderCell = (CalendarCell *)sender;
paf.datos = senderCell.dataDic;
}
}
Both viewController viewDidLoad methods are calling super at the start of the method.
As I told before, if I just tap on other tab and then come back to this one, the slide back animation from "Partidos Activos En Fecha" viewController works as expected, it's only when I start the application and go directly to this viewController when the slide back animation doesn't work, and it just gets to the caller viewController without animation.
Hope I added enough info, if not just tell me and I will add it again.
I finally found where the problem was, I was missing a call to super in the viewDidAppear method but in UITabBarController!, I was checking only viewControllers for the tabs but not the tabbarviewcontroller. #rdelmar was right.
I had the exact same problem. The cause for me was an empty viewDidAppear:animated method in my UITabBarController. Once I deleted that method, the animation worked normally again.
I think this it's what you want. If I understand, your problem is handle the stack of the navigation controller right? So, check that link.
I know it's a very long shot and the problem description is vague at best, but I'm hoping someone might have encountered that as well.
I have a UIViewController subclass that is being presented modally. The view of the controller contains some UIButtons and some UITextFields. The view controller might be presented multiple times during a user session; it is created every time it's presented and gets destroyed when it's dismissed. Most of the time everything works as expected, however, sometimes the text fields don't respond to user touch, i.e. tapping them does not bring up the keyboard. The buttons on the view work fine, it's just the text fields that become disabled.
What could possibly be causing this?
Turns out the reason UITextFields inside a modally presented view controller were not responding was that one of the long-living view controllers in the app called [self becomeFirstResponder] on itself, but never called [self resignFirstResponder]. It had to be the first responder in order for it to receive remote controls events when the app was playing music.