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

我想使用以下UITextFieldDelegate方法:

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

textField.text.stringByReplacingCharactersInRange(???, 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))
    }
}

详情请看这里

其他回答

Swift 3.0 beta版官方文档在标题String下为这种情况提供了标准解决方案。UTF16View中的UTF16View元素匹配NSString字符标题

这与Emilie的回答相似,但是,因为你特别问如何将NSRange转换为Range<String。索引>,你会这样做:

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

     let start = advance(textField.text.startIndex, range.location) 
     let end = advance(start, range.length) 
     let swiftRange = Range<String.Index>(start: start, end: end) 
     ...

}

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))
    }
}

详情请看这里

NSString版本(相对于Swift String)的replacingCharacters(in: NSRange, with: NSString)接受NSRange,所以一个简单的解决方案是先将String转换为NSString。在Swift 3和2中,委托和替换方法的名称略有不同,所以这取决于你使用的Swift:

斯威夫特3.0

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

  let nsString = textField.text as NSString?
  let newString = nsString?.replacingCharacters(in: range, with: string)
}

快2.倍

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

    let nsString = textField.text as NSString?
    let newString = nsString?.stringByReplacingCharactersInRange(range, withString: string)
}

你需要使用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)