Search code examples
iosswiftuitextfieldseguebecomefirstresponder

Keyboard appears twice when UITextField becomes first responder after custom segue performed


So the problem is: when I push a button on a source view the custom segue performed.

Here is the code (pretty standard):

class FirstCustomSugue: UIStoryboardSegue {
override func perform() {

    let initalView = self.source.view as UIView?
    let destinationView = self.destination.view as UIView?

    let screenHeight = UIScreen.main.bounds.size.height
    let screenWidth = UIScreen.main.bounds.size.width

    initalView?.frame = CGRect(x: 0, y: 0, width: screenWidth, height: screenHeight)
    destinationView?.frame = CGRect(x: screenWidth, y: 0, width: screenWidth, height: screenHeight)

    let appWindow = UIApplication.shared.keyWindow
    appWindow?.insertSubview(destinationView!, aboveSubview: initalView!)

    UIView.animate(withDuration: 0.4, animations: {
        // Left/Right
        initalView?.frame = (initalView?.frame.offsetBy(dx: -screenWidth, dy: 0))!
        destinationView?.frame = (destinationView?.frame.offsetBy(dx: -screenWidth, dy: 0))!
    }) { (Bool) in
        self.source.present(self.destination, animated: false, completion: nil)
    }
}

}

I call myTextField.becomeFirstResponder() in viewDidiAppear (call to super is included).

When I set a simulator's «Slow animations» On I can clearly see that keyboard first appears alongside the animation and after animation is complete it reappears.

I included the example а the segue because when I switch to the standard segues there is no such problem. If you need any other code example I will update a post.

Using custom segues because I am not using navigationController for views I transition between and default modal segues are not an option.

My guess is that viewDidAppear is called twice, because even when I set myTextField.isUserInteractionEnabled = false and myTextField.isEnabled = false in viewWillAppear or viewDidLoad (before or after the super in both methods) and then setting those to true in viewDidAppear right after call to super the result is the same.

TNX in advance!


Solution

  • Changed segue’s perform to the following:

        let sourceViewController = self.source
        let destinationViewController = self.destination
    
        let transition = CATransition()
    
        transition.duration = 0.5
        transition.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)
        transition.type = kCATransitionMoveIn
        transition.subtype = kCATransitionFromRight
    
        let appWindow = UIApplication.shared.keyWindow
        appWindow?.layer.add(transition, forKey: kCATransition)
    
        sourceViewController.present(destinationViewController, animated: false, completion: nil)ere