如何将NSRange转换为Range<String。索引>在Swift?

我想使用以下UITextFieldDelegate方法:

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

textField.text.stringByReplacingCharactersInRange(???, withString: string)


当前回答

extension StringProtocol where Index == String.Index {

    func nsRange(of string: String) -> NSRange? {
        guard let range = self.range(of: string) else {  return nil }
        return NSRange(range, in: self)
    }
}

其他回答

在公认的答案中,我发现可选选项很麻烦。这适用于Swift 3,似乎对表情符号没有问题。

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

  guard let value = textField.text else {return false} // there may be a reason for returning true in this case but I can't think of it
  // now value is a String, not an optional String

  let valueAfterChange = (value as NSString).replacingCharacters(in: range, with: string)
  // valueAfterChange is a String, not an optional String

  // now do whatever processing is required

  return true  // or false, as required
}

你需要使用Range<String。索引>而不是经典的NSRange。我这样做的方式(也许有一个更好的方式)是通过获取字符串的字符串。索引移动它与前进。

我不知道你要替换的范围是什么,但让我们假设你想替换前两个字符。

var start = textField.text.startIndex // Start at the string's start index
var end = advance(textField.text.startIndex, 2) // Take start index and advance 2 characters forward
var range: Range<String.Index> = Range<String.Index>(start: start,end: end)

textField.text.stringByReplacingCharactersInRange(range, withString: string)

Swift 5解决方案

简短的回答带有主要的扩展

extension NSRange {

    public init(range: Range<String.Index>, 
                originalText: String) {

        self.init(location: range.lowerBound.utf16Offset(in: originalText),
                  length: range.upperBound.utf16Offset(in: originalText) - range.lowerBound.utf16Offset(in: originalText))
    }
}

详情请看这里

func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
    
    guard let current = textField.text, let r = Range(range, in: current) else {
        return false
    }
    
    let text = current.replacingCharacters(in: r, with: string)
    // ...
    return true
}
func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {

       let strString = ((textField.text)! as NSString).stringByReplacingCharactersInRange(range, withString: string)

 }