Weird resignFirstResponder behaviour with UITextfield - ios

I have a textfield that is on a modally presented viewController that is inside a navigation controller, when i use
- (BOOL) textFieldShouldReturn:(UITextField *)textField {
[textField resignFirstResponder];
return YES;
}
the keyboard hides as expected when i push return, but for some reason the whole view that the textfield is in sort of shrinks to the top left and leaves all the subviews shifted to the left. its a really simple view so im not sure what is going wrong, is there a different way to hide the keyboard that could potentially avoid this problem?
here are some screenshots
ive attached the full code here: http://pastebin.com/PKMXEL4U

Ok wow, weirdest symptoms for such a silly mistake, turns out i forgot to put [super viewWillAppear:animated]; in the viewWillAppear it took me reconstructing the whole class and storyboard in a separate project to find that out >.<

Related

How do I make inputAccessoryView stay on screen when using drag to dismiss?

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

Why is my navigation view popping?

I've a problem, when I'm scrolling up and down in the table view highlighted in the view below it can be fine for a few scrolls up and down and then seemingly randomly it pops back to the view before (but doesn't update the screen so it just looks stuck in the table view) Sometimes on the first scroll it pops the view too.
I don't really want to post my whole class unless someone thinks it's necessary but I would be grateful if someone could point me in the right direction as to why this would be happening.
- (void) viewWillDisappear:(BOOL)animated
{
NSLog(#"Is this being dismissed: %d", [self isBeingDismissed]); // returns 0
NSLog(#"isMovingFromParentViewController %d", [self isMovingFromParentViewController]); // returns 0
NSLog(#"viewWillDisappear occured on bookmark table");
}
-(void)willMoveToParentViewController:(UIViewController *)parent {
NSLog(#"This VC has has been pushed popped OR covered"); // this is happening
if (!parent)
NSLog(#"This happens ONLY when it's popped"); // this is happening
}
Could anyone tell me a way to find out what is calling the willMoveToParentViewController or viewWillDisappear? I've had a look in the debug log with a pause but it just says before
A breakpoint on willMoveToParentViewController shows this in Thread 1
0 [bookmarkTableViewController willMoveToParentViewController:]
1 _popViewControllerNormal
A breakpoint on viewWillDisappear
0 [bookmarkTableViewController viewWillDisappear:]
1 [UIViewController _setViewApppearState:isAnimating:]
So as summary, I can use it fine for 10 scrolls up or down and then it happens, or maybe it will happen on the first scroll so it looks random to me. If anyone thinks it'll help me sharing my entire class it'll help but it's pretty much just a generic table view.
EDIT
I've found that it's something to do with the segue.
When I segue with just 'Show (e.g Push)', it lets me have the navigation back button but crashes. When I do 'Show Detail (e.g replace)', it never crashes which leads me to think I could just fake the navigation back button but really i'd like to know why this is happening.
EDIT 2:
I've noticed that the problem occurs even with a blank table list so it has nothing to do with that. When I spam scrolling up and down on the totally empty new table view controller it does the exact same thing.
For some reason scrolling up and down in scroll area eventually locks the tableview UI and calls the previous view controllers viewwillappear
EDIT 3:
I think it might have something to do with the navigation controller, I just stripped hte project to its bare bones and i noticed sometimes instead of table scrolling it's doing the side-swiping navigation back gesture thing
EDIT 4:
Yep it was that, I can't even fix it apparently with objective-c as of yet it says https://stackoverflow.com/a/19019924/4056064
I found the reason. this navigation gesture turn off thing doesn't work so occasionally a back navigation sweep was detected rather than a scroll and it called my previous view and then returned it to the current one. source: https://stackoverflow.com/a/19019924/4056064 happy to hear if anyone has any work arounds that.
Edit: found a work around
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer
{
return NO;
}
if ([self.navigationController respondsToSelector:#selector(interactivePopGestureRecognizer)]) {
self.navigationController.interactivePopGestureRecognizer.enabled = NO;
self.navigationController.interactivePopGestureRecognizer.delegate = self;
}

UITextField that is always first responder

I have a ViewController that is just a textfield, a next button, and a back button. I want the text field to always be editable while having the keyboard always present. I also want to customize the keyboard to be my own, but that will come once I figure this part out.
EDIT: The keyboard in my case will only actually be a keypad with 10 digits and a backspace key
What is the best way to go about this? I've been working around with having a UITextField that works with a custom keyboard view, and then make that the first responder when the view loads, but maybe there are better ways.
Thanks in advance!
To make a UITextField always use the keyboard...
In the viewDidAppear or viewWllAppear function do this...
[self.textField becomeFirstResponder];
This will make the keyboard appear and the textField respond to the input.
To dismiss the keyboard you have to run...
[self.textField resignFirstResponder];
As long as you don't run this it will keep keyboard focus.
In the view controller's viewWillAppear: method you can call becomeFirstResponder on the text field. This will make the keyboard appear automatically when the view controller appears. As long as there is no other way to dismiss the keyboard, that is all you need.
Of course on the iPad there is a button on the keyboard to dismiss it. If you want to stop that button from working then implement the following delegate method:
- (BOOL)textFieldShouldEndEditing:(UITextField *)textField {
return NO;
}
And in case you want to really have your own keyboard. create a view properly sized and beautified ;).. and put in the textFiled's inputView property.
textField.inputView = your custom keyboard view
Cheers.

Toolbar disappears when hiding keyboard

I have a nav controller with a toolbar. I made the toolbar also appear on top of the keyboard when the keyboard appears. When I dismiss the keyboard, the toolbar disappears, leaving a black rectangle at the bottom of the screen, just where the toolbar should be without the keyboard.
Here's how I init the toolbar:
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[self.navigationController setToolbarHidden:NO];
// this makes sure the toolbar appears on top of the keyboard
// instead of going below it.
// _nameText is a UITextField
_nameText.inputAccessoryView = self.navigationController.toolbar;
}
This is how I hide the keyboard:
- (BOOL)textFieldShouldReturn:(UITextField *)textField {
[textField resignFirstResponder];
[self.navigationController setToolbarHidden:NO]; // this doesn't help
return NO;
}
I tried also doing [self.view setNeedsLayout], but that didn't work.
EDIT: I suspect this may have to do with the fact that I assign the toolbar to be the input accessory view of my text field. I think that the text field hides its accessory view when the keyboard goes away. I still don't know how to override that behavior though.
EDIT 2: I discovered that self.navigationController.toolbar.superview is nil after the keyboard is gone.
OK, so while I couldn't solve the problem head-on, I found an acceptable workaround.
Create a .xib for your toolbar
Load the toolbar from (1) into an object
assign that object to the inputAccessoryView property of your text field
set up the target and the actions for the buttons in this toolbar, so you can respond to clicks
You are now all set. Your original toolbar (which you presumably have created in the Interface Builder) is only visible when the keyboard is hidden. When the keyboard is visible, the original toolbar cannot be seen, but your other one (created with the steps described above) now appears above the keyboard. Bingo!
If anyone has a more elegant solution to this problem, I'd be happy to hear about it :)
#BlackRider, I ran into the same exact issue as you. It is quite annoying.
I didn't want to set up 2 different toolbars as a workaround, as I didn't want to handle the state of the toolbar buttons in 2 different places.
I've resorted to using the approach discussed here in the answer that uses notifications: iPhone: How to fix inputAccessoryView to View?
It's working ok - my gut reaction is that I'll run into issues when trying on various device sizes / orientations.

iPhone OS 3.2 (iPad) Modal View question

I am presenting a UIViewController as a modal viewcontroller with modalPresentationStyle = UIModalPresentationFormSheet. I have few UITextFields on its view.
My issue is that when I try to dismiss the keyboard ([textfieldname resignFirstResponder]), it doesn't do anything. However when I change the modalPresentationStyle to UIModalPresentationPageSheet, it works.
This seems to be a bug. Has any one faced similar problems and found a work around? Could I be doing anything dumb and silly?
I ran into this same issue with UITextView, I ended up subclassing UITextView and overriding resignFirstResponder as follows...
- (BOOL)resignFirstResponder{
[super resignFirstResponder];
// For some reason, UITextView doesn't like to give up first responder, ever....
return YES;
}
I haven't checked if this is still necessary in 4.3 but it was definitely needed in 3.2 in some cases.

Resources