How to prevent duplicate and empty strings in tableview array with UIalertcontroller?

func savingIsAllowed(with name: String) -> Bool{
    return name.characters.count > 0 && !IncomeExpense.shared.categories.contains { $ == name }

func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {

    let name = textField.text ?? ""

    alertController.actions[0].isEnabled = savingIsAllowed(with: name)

    return true

In this screenshot is a UIalertcontroller that appears when the add button is tapped with a textfield whose delegate is the tableviewcontroller. I would like its save button to be disabled instantly whenever the string in the textfield is already in the list or is empty. With this code, empty strings are prevented, but not duplicates. TextFieldEditingDidBegin and DidEnd behave similarly. The save button is only disabled when I backspace. What’s wrong with it?

You are implementing shouldChangeCharacters, and you seem not to understand what it does. At that moment the characters have not yet changed. For example, if the user types “Jo” and then “b”, you get shouldChangeCharacters before textField.text is “Job” (because shouldChangeCharacters is exactly asking you whether to enter the “b”). Therefore your test, looking at textField.text, fails to work.

Also there’s another reason your test fails to work: as rmaddy points out, you are validating against the replacement string for the range (savingIsAllowed(with: string)), not the entire text. [EDIT Okay, now you’re dancing around changing your code faster than I can type. I don’t play that game, however.]

What you want to do is start over entirely. Implement a control event for the text field’s editingChanged event and respond to that.