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?