I have View Controller that accepts text input using an UITextView called "myTextView".
When I segue to myTextView, I use the following:
self.performSegueWithIdentifier("myTextView", sender: self)
myTextView is presented. Then next the keyboard is displayed after viewDidAppear:
override func viewDidAppear(animated: Bool) {
self.myTyping.becomeFirstResponder()
}
Everything animates smoothly. However I want the keyboard to display at the same time as the segue animating and being displayed together and not one after the other.
I can do that with the call for the keyboard with the segue call. However, the animation is jittery and choppy, and not smooth.
How can I both segue to myTextView View Controller and display the keyboard at the same time without any animation jitters?
Related
I wrote a custom UIViewController for showing slide-up menu. Every time calling present(thisViewController) will show up the menu with animation and background is black transparent with alpha 0.5.
But I got problem that every first time the viewController is present, animation is not fully run, background color seems no transparent, and the slide menu is not shown the whole menu that there is one line outside of screen.
I searched the internet and found the reason is the animation not done, because the viewController is just initialed and animation is too fast shown. If I dismiss and present it
again will show as what I expected.
So I want to have a method to pre-initial the slide menu ViewController that it can run viewDidLoad before I present it. Is there a way to do this?
Update:
I call UIView.animate() in viewWillAppear(). I think the first time it ran viewWillAppear() too short time that it just initialized UIView and immediately animated, so it interrupted in the animate action. When the second time presenting this viewController, it showed the animation fully because it was shown before.
I add the views in viewDidLoad() but it won't be called until presenting the viewController.
Hmm.. I want to have a method to let the slide-up menu viewController pre-do viewDidLoad() in the other viewController.
#Shadowrun Thank you.
In A UIViewController, I initial the SlideMenu ViewController, and make the SlideMenu call ViewController.loadViewIfNeeded() in viewDidLoad()
class viewController: UIViewController {
var slideUpMenu = SlideMenuViewController()
override func viewDidLoad() {
super.viewDidLoad()
slideUpMenu.loadViewIfNeeded()
}
func pressButton() {
present(slideUpMenu, animated: false)
}
}
It shows perfectly.
iOS 11.2, Xcode 9.2
I've tried all the ways to dismiss keyboard on viewDidDisappear of the old UIViewController AFTER a new UIViewController is pushed into UINavigationController stack. But with no luck.
If I dismiss it on viewWillDisappear - it will be dismissed but with animation DURING push animation. It is not the desired behaviour. I want the old UIViewController's keyboard to be dismissed only when the controller is no longer visible.
The behavior should be like in Telegram app:
In any dialog with visible keyboard press on opponents avatar and you'll be pushed to opponents account information. Then, if you press back button, you'll be redirected back to a dialog. But the keyboard will be already dismissed.
Any help is appreciated!
P.S. The question might look like a duplicate, but I have failed to make it work with the solutions I found.
Edit 1.
I have created a small TEST PROJECT which represents a failure to achieve the desired behavior.
In order to reproduce the undesired behavior:
Launch the app.
Tap on UITextField or UITextView and wait for the keyboard to appear.
Tap on "Next" button and wait for a new controller to be pushed.
Tap on "Back" button and wait for a new controller to be popped.
As a result - the initial view controller will have the active keyboard after the push/pop actions. I need the keyboard to be hidden after the push/pop actions. Also, the keyboard should not be dismissed before the initial view controller becomes invisible, it should be dismissed after viewDidDisappear action.
There are cases where no text field is the first responder but the keyboard is on screen. In these cases, the above methods fail to dismiss the keyboard.
Use the property: isEditable of your textView. Here is a tested code:
override func viewWillAppear(_ animated: Bool) {
self.viewTextView.isEditable = false
super.viewWillAppear(animated)
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
self.viewTextView.isEditable = true
}
Results:
Comments from #iWheelBuy:
Sometimes, text views will have inputAccessoryView. The way you do it
will make the keyboard disappear, but the inputAccessoryView will
remain... That is why you should also make inputAccessoryView = nil
or inputAccessoryView = UIView() when setting isEditable = false
The problem happens because responders are managed (restored, saved) by UIKit between viewWillAppear and viewDidAppear, just before view has appeared, and between viewWillDisapear: and viewDidDisapear:, just before view has disappeared. That is why any change made to responders is visible during animation.
Instead of removing responders, to get the effect you want, you can prevent views from becoming responders before view appears again.
The simplest way to do this for UITextField and UITextView is to temporary disable interaction just before view will appear, and then restore it after the view did reappeared.
override func viewWillAppear(_ animated: Bool) {
self.viewTextField.isUserInteractionEnabled = false
self.viewTextView.isUserInteractionEnabled = false
super.viewWillAppear(animated)
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
self.viewTextField.isUserInteractionEnabled = true
self.viewTextView.isUserInteractionEnabled = true
}
This will give you the same effect Telegram has.
I have the following UI elements:
A table view cell with an associated segue
A save button that shows an alert if data is missing
A table view cell's segue does not run until the user lets go of the button. So they can do the following:
Tap and hold the cell
While holding cell, tap the save button
Let go of cell
This brings up the alert and performs the segue behind it! Seems like iOS should not run the segue, but at least on iOS 10 it allows this behavior. How can I fix this issue?
Add the following code to your view controller:
override func shouldPerformSegue(withIdentifier identifier: String, sender: Any?) -> Bool {
return presentedViewController == nil
}
This will prevent any segue when a modal view controller is presented.
I have a TableViewController and I would like to trigger a segue within its navigation bar. I created the segue in the storyboard to my new ViewController. However if I click the bar button item, the view does not appear.
Instead the bar button item becomes inactive (greyed out) and the app freezes. There is no error message and the app does also not crash. The prepareForSegue method in my TableViewController also gets called
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
print("prepare for segue called")
print("destination view controller = \(segue.destinationViewController.description)")
}
I did the following things:
created a custom view Controller class for the second screen (in my storyboard and as a .swift file). I assigned the respective ViewController in the storyboard to my custom view controller in the Identity inspector
created an IBAction for a click event on the button and triggered
the segue programatically. The result remains the same.
prepareForSegue is called. The destionationViewController is correct
but does not show up. I removed this IBAction afterwards.
My destination view controller looks like this
class EnterUserDataViewController : UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
print("EnterUserDataViewController viewDidLoad called")
}
}
viewDidLoad never gets called even though the right segue has been triggered.
Can someone please give me a hint on why this happens?
You wouldn't happen to have a rogue breakpoint set somewhere would you?
If I put a breakpoint somewhere in the view loading cycle it recreates the exact symptoms you are describing.
I have Viewcontroller with AutoLayout for its views and subviews
I added it as a Modal view controller
It starts fitting well as in image
but After textField starts edits it changes to
I tried to add
func textFieldShouldBeginEditing(textField: UITextField) -> Bool {
self.view.setTranslatesAutoresizingMaskIntoConstraints(false)
return true
}
it works well when he starts editing but distorts again when user dismiss keyboard