2

I have 2 text fields on 2 different VC's.

The intended behaviour is for the text fields to become first responder (automatically load the keyboard without needing to tap) at the point the page loads.

When the user presses 'done' on the keypad, it should resign the responder and dismiss the keypad.

For some reason, when I add the code to allow the 'done' button to resign the first responder, it seems to be preventing the field becoming first responder when the page is loaded.

On VC1, I have :

//set the text field as first responder to auto open keyboard

override func viewDidAppear(_ animated: Bool) {
        authorNameOutlet.becomeFirstResponder()
    }

and then

//make the done button on the keypad dismiss the keyboard

func textFieldShouldReturn(_ textField: UITextField) -> Bool {
        authorNameOutlet.resignFirstResponder()
        return true
    }

This page does not auto open the keypad and set first responder on page load.

On my 2nd VC, I've removed the textFieldShouldReturn method and the first responder works perfectly, auto opening the keypad on the textfield with tapping. However, in this case the 'done' button now does nothing because the 'textFieldShouldReturn' isn't there.

I can't see what I'm doing wrong, the way I see it I'm setting my first responder in the right place (viewDidAppear) and the responder should only resign once done is pressed?

I also have some validation but don't think that's relevant :

//disable button if not all fields completed when finished editing

    func textFieldDidEndEditing(_ textField: UITextField) {
        if titleOutlet.text?.isEmpty == false {
            confirmButtonOutlet.isEnabled = true
        } else {
            confirmButtonOutlet.isEnabled = false
        }
    }

I've looked at other answers but this is a pretty simple implementation and can't work out why it isn't working!

UPDATESo I just noticed that the page transitions slightly differently and remembered VC1 (where it isn't working) is part of a PageView Controller and the page where it IS working isn't (it's just segued from there but is a normal VC).

I also can confirm that adding the textFieldShouldReturn to the second VC doesn't make a difference so that's a red herring.

Is there any reason being part of a PVC would change the behaviour? Wonder if there's a different delegate to subscribe to in that VC?

UPDATE whole code for VC1 where is isn't working (NB. i've tried removing the page fade but that doesn't impact it and this is the same on the 2nd VC where it is working)

import UIKit
import RealmSwift

class OnboardingNameVC: UIViewController, UITextFieldDelegate {

    @IBOutlet weak var authorNameOutlet: UITextField!
    @IBOutlet weak var titleOutlet: UILabel!
    @IBOutlet weak var confirmButtonOutlet: UIButton!

    @IBAction func confirmNamePressed(_ sender: Any) {
        addAuthorName()
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        authorNameOutlet.attributedPlaceholder = NSAttributedString(string: "Joe Bloggs",
                                                               attributes: [NSAttributedStringKey.foregroundColor: UIColor.lightGray.withAlphaComponent(0.5)])
        authorNameOutlet.delegate = self
        confirmButtonOutlet.isEnabled = false
        authorNameOutlet.setBottomBorder(withColor: UIColor.lightGray)
    }

    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        authorNameOutlet.becomeFirstResponder()
    }

    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        animateFade()
    }

    func addAuthorName() {
        let realm = try! Realm()
        let authorToCreate = AuthorPreferences()

        authorToCreate.AuthorName = authorNameOutlet.text!

        try! realm.write {
            realm.add(authorToCreate)
            performSegue(withIdentifier: "nameToTitleSegue", sender: self)
        }
    }

    //disable button if not all fields completed when finished editing

    func textFieldDidEndEditing(_ textField: UITextField) {
        if authorNameOutlet.text?.isEmpty == false {
            confirmButtonOutlet.isEnabled = true
        } else {
            confirmButtonOutlet.isEnabled = false
        }
    }

    func textFieldShouldReturn(_ textField: UITextField) -> Bool {
        authorNameOutlet.resignFirstResponder()
        return true
    }


    //animations
    func animateFade() {

        let labels : [UIView]  = [titleOutlet, authorNameOutlet, confirmButtonOutlet]

        var delay = 0.3
        let duration = 1.2

        for label in labels {
            label.fadeIn(duration: duration, delay: delay)
            delay += 0.2 // Increment delay
        }

    }
}

EDIT - SOLVED!

After realising the different page transition behaviour I realised that VC1 was part of a PageViewController.

As a result I needed to add this to the viewDidAppear :

override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        DispatchQueue.main.async {
            self.authorNameOutlet.becomeFirstResponder()
        }
    }

It now works fine.

TLDR: If you have a textField within a pageviewController and become first responder isn't working as normal you probably need to add to the dispatch queue as per above!

nc14
  • 539
  • 1
  • 8
  • 26
  • I don't see any issue with your code. Check if you are calling view.endEditing(true) somewhere. – PGDev Jun 26 '19 at 09:18
  • hey thanks for helping - i'm calling didEndEditing for text validation but just to enable/disable a button depending on if the field has text or not - i've added to the bottom of the question – nc14 Jun 26 '19 at 09:21
  • Are you running it in Simulator? – PGDev Jun 26 '19 at 09:22
  • Why are you not calling super.viewDidAppear()? – Agent Smith Jun 26 '19 at 09:23
  • Yes in simulator but also on a real device, i hadn't even realised it was missing i've added back in but still not working – nc14 Jun 26 '19 at 09:28
  • Try pressing Cmd+K when running on simulator and run it again. Check if the keyboard appears. – PGDev Jun 26 '19 at 09:42
  • Also, add whole VC1 code if possible so we can debug the issue. – PGDev Jun 26 '19 at 09:43
  • thanks for helping guys - I realised how to solve it after realising it was part of a PVC and have added the solution for others in the question and have updated the title to make it easier for others who might be searching for same issue! – nc14 Jun 26 '19 at 09:51
  • To make it complete, here is an explanation comment of what's going on: https://stackoverflow.com/questions/21032056/uitextfield-losing-firstresponder-after-view-appears#comment67029798_21069878 – Arkadii Nov 01 '20 at 13:19

0 Answers0