0

Why does my replacementTextHasLetter constant not prevent me from pasting in a letter into my textfield with the below conditional?

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

    let existingTextHasDecimalSeparator = textField.text?.range(of: ".")
    let replacementTextHasDecimalSeparator = string.range(of: ".")

    let charactersNotAllowed = NSCharacterSet.letters
    let replacementTextHasLetter = string.rangeOfCharacter(from: charactersNotAllowed)

    if existingTextHasDecimalSeparator != nil && replacementTextHasDecimalSeparator != nil && replacementTextHasLetter != nil {

        return false

    }

    return true

}

But when it has its own separate conditional it works?

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

    let existingTextHasDecimalSeparator = textField.text?.range(of: ".")
    let replacementTextHasDecimalSeparator = string.range(of: ".")

    let charactersNotAllowed = NSCharacterSet.letters
    let replacementTextHasLetter = string.rangeOfCharacter(from: charactersNotAllowed)

    if existingTextHasDecimalSeparator != nil && replacementTextHasDecimalSeparator != nil {

        return false

    }

    if replacementTextHasLetter != nil {

        return false

    }

    return true

}

EDIT: I figured it out. It's impossible for the first example to work since existingTextHasDecimalSeparator & replacementTextHasDecimalSeparator are basically determining if there is a decimal in the textfield and if the user is trying to enter a new one, to return false. When I add

&& replacementTextHasLetter != nil

to the conditional, it is just not really serving a purpose since all of the statements can't be true at the same time. Thank you @sonofabeach

tophst
  • 3
  • 3
  • 1
    Putting it in its own `if` condition makes it effectively an "OR" ( `||` ), not an "and". You are using `&&`, not `||`. Which do you really want? – Son of a Beach Dec 21 '16 at 00:35
  • Why can't it be an "AND"? – tophst Dec 21 '16 at 01:17
  • It can be. It can be whatever you want it to be. But don't expect "AND" to behave the same as "OR". Your question was (to paraphrase my understanding)...Why do the two blocks of code that you posted not behave the same? The answer is that one is explicitly using an "AND" to combine conditions (`&&`) and the other is implicitly equivalent to using an "OR" to combine conditions. "AND" and "OR" behave very differently. If that answer is insufficient, then you may need to clarify the question more. – Son of a Beach Dec 21 '16 at 01:21
  • I understand that. I'm having trouble understanding why the "OR" , or separate "if", statement worked in the first place @SonofaBeach AKA why did the "OR" work and not the "AND"? This seems very fundamental but I just do not get it. – tophst Dec 21 '16 at 01:24
  • You need to provide more information, in that case. You need to demonstrate what the values of each of the 3 items being tested in the `if` conditions are. If you do this, then people here can help you. I suspect that if you do this, the answer may also become obvious to yourself. You can use either logging (eg, `NSLog()`) to do this, or you can use stepping through the code in the debugger to do this. Post your results here. – Son of a Beach Dec 21 '16 at 01:26

1 Answers1

0

These two lines:

if existingTextHasDecimalSeparator != nil && replacementTextHasDecimalSeparator != nil {
    return false
}

if replacementTextHasLetter != nil {
    return false
}

Are the effectively the same as:

if (existingTextHasDecimalSeparator != nil && replacementTextHasDecimalSeparator != nil) || replacementTextHasLetter != nil {
    return false
}

Note the use of || instead of && for the last condition.

rmaddy
  • 314,917
  • 42
  • 532
  • 579