0

For a tableView of secure-textfield-containing cells, whenever I change the selected textfield the keyboard flickers to a plain gray view briefly. The keyboard functions normally if none of the text fields are secure. Additionally, I get an automatic strong password error that doesn't occur when the text fields aren't inside a tableView.

[AutoFill] Cannot show Automatic Strong Passwords for app bundleID: com.SamsonLLC.TextFieldTest due to error: iCloud Keychain is disabled

I have to imagine that making modular forms out of a UITableView is fairly common, so I'm assuming/hoping adding text fields to cells isn't just broken.

Here is the minimal code to reproduce the issue. I could add a github repo if that's preferred. All the code could just be pasted into ViewController.swift after making a single-view app.

ViewController:

class ViewController: UIViewController {

    // Configure tableView
    lazy var tableView: UITableView = {
        let tableView = UITableView()
        tableView.register(TextFieldCell.self, forCellReuseIdentifier: "TextFieldCell")
        tableView.rowHeight = 100
        tableView.delegate = self
        tableView.dataSource = self
        return tableView
    }()

    override func viewDidLoad() {
        super.viewDidLoad()
        setup()
    }

    // Layout tableView
    func setup() {
        view.addSubview(tableView)
        tableView.translatesAutoresizingMaskIntoConstraints = false

        NSLayoutConstraint.activate([
            tableView.topAnchor.constraint(equalTo: view.topAnchor),
            tableView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
            tableView.bottomAnchor.constraint(equalTo: view.bottomAnchor),
            tableView.leadingAnchor.constraint(equalTo: view.leadingAnchor)
        ])
    }
}

extension ViewController: UITableViewDataSource {
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        3
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "TextFieldCell", for: indexPath) as! TextFieldCell

        let row = indexPath.row

        // First textfield is normal, rest are secure text entry
        switch row {
        case 0:
            cell.textField.isSecureTextEntry = false
            cell.textField.keyboardType = .emailAddress
        default:
            cell.textField.isSecureTextEntry = true
            cell.textField.keyboardType = .default
        }
        return cell
    }
}

extension ViewController: UITableViewDelegate {}

TextFieldCell:

class TextFieldCell: UITableViewCell {

    // Configure text field
    let textField: UITextField = {
        let textField = UITextField()
        textField.layer.borderColor = UIColor.lightGray.cgColor
        textField.layer.borderWidth = 2.0
        return textField
    }()

    override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
        super.init(style: style, reuseIdentifier: reuseIdentifier)
        setup()
    }

    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    // Layout cell
    private func setup() {
        contentView.addSubview(textField)
        textField.translatesAutoresizingMaskIntoConstraints = false

        let margins = contentView.layoutMarginsGuide

        NSLayoutConstraint.activate([
            textField.centerYAnchor.constraint(equalTo: contentView.centerYAnchor),
            textField.trailingAnchor.constraint(equalTo: margins.trailingAnchor),
            textField.leadingAnchor.constraint(equalTo: margins.leadingAnchor)
        ])
    }
}

extension NSLayoutConstraint {
    func withPriority(_ priority: UILayoutPriority ) -> NSLayoutConstraint {
        self.priority = priority
        return self
    }
}

EDIT:

The problem is linked to iOS automatically detecting the view controller as a login screen an implementing the automatic strong password feature. Maybe this would work If I supported that feature, but it requires a developer program membership and I don't want to pay $99 to find out (Though I guess you could argue I'm going to need to become a member at some point anyways).

Unfortunately it's really hard to break this automatic login sign in/sign up screen detection at this point. The only way I can get it to stop is to add a 1 pixel high dummy textfield with user interaction disabled between my two secure textfields. This switches the text fields in the tableview from [normal, secure, secure] to [normal, secure, normal (dummy), secure] and breaks the sign in/sign up form recognition.

Another solution is to implement the password hiding feature yourself and not use secure text fields. You can check Sandy Akbar's solution here: iOS 11 disable password autofill accessory view option?

  • Do you see the same thing on a device as you do the simulator? Also, this is a bit unrelated, but instead of pinning your textfield to the center Y anchor, you should pin the top and bottom so the cell has a height. – Rob C Dec 22 '19 at 13:28
  • Unfortunately I don't have an iOS device right now so I can't check if it's different. – Edward Samson Dec 22 '19 at 19:41

0 Answers0