为什么 range.length 值在 shouldChangeCharactersInRange 委托方法中更改退格键?

Why range.length value changes for backspace in shouldChangeCharactersInRange delegate methos?

在我将用户限制为最多 24 个字符后,我试图弄清楚这一行对退格键的效果如何。但我不知道它是如何工作的。

我试图找出 range.length 的值,如果我插入一些字符,它会设置为 0。但是当我在删除字符时按下后退按钮时,我将值设置为 1?这是为什么?

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

    println("range is \(range)")
    println("range location is \(range.location)")
    println("range length is \(range.length)")    

    if (textlength - (range.length) + count(string)) > 24 {                  
       textField.layer.borderColor = UIColor.redColor().CGColor
       textField.layer.borderWidth = 1.0

       println("\(newString)")
       return false
    }        
    return true
}

尝试插入 3 个字符长的文本。然后 select all 并点击 cut。 您应该会看到如下内容:

range is (0,3)
range location is 0
range length is 3

插入时长度为 0,因为没有 selected。您只有 光标 位置。当您删除时,您的 range.length 将是可以删除的字符串的长度。 当你回击时,你只是删除了最后一个字符,因此 range.length 是 1.

进行这种长度检查的最简单方法可能是实际应用替换,然后测试结果字符串。

func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
    let current = textField.text
    let modified = current.stringByReplacingCharactersInRange(range, withString: string)

    if (modified.length > 24 {                  
       textField.layer.borderColor = UIColor.redColor().CGColor
       textField.layer.borderWidth = 1.0

       println("\(modified)")
       return false
    }        
    return true
}

该方法说 shouldChangeCharacterInRange,所以当你插入一个新字符时,不会替换或删除现有字符,因此它给你的长度为 0。而当你删除一个字符,它会return你要删除的字符范围,显然是1.

例如:

假设您有一个文本 Hello World 这包含 11 个字符。

现在当您插入一个新字符 ! 时,它会 return 您将在最后一个字符之后插入这个新字符的范围,即 {11,0}.

现在当你删除一个字符时,比如说最后一个字符,它会return你最后一个字符的范围,即{10,1}

您可以通过长按一些文本并将其删除来进行测试。假设您长按“World”并将其删除。这将 return 您的范围长度为 5,即 {5,5}


因此您需要在附加更改后检查文本,即

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

    let stringAfterAppendingChanges = textField.text.stringByReplacingCharactersInRange(range, withString: string)

    if (stringAfterAppendingChanges.length > 24 {                  
       textField.layer.borderColor = UIColor.redColor().CGColor
       textField.layer.borderWidth = 1.0

       println("\(stringAfterAppendingChanges)")
       return false
    }

    textField.layer.borderColor = UIColor.clearColor().CGColor        
    return true
}