我正在为 UITextField 编写一个验证器,我得到了一个现有字符串、替换字符串和一个发生替换的 NSRange。我有两个版本的代码来获取新的候选字符串:
a.明确使用NSString
func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
let existingString: NSString = textField.text ?? ""
let candidateString = existingString.stringByReplacingCharactersInRange(range, withString: string)
//do validation on candidateString here
return true
}
b.生成Range<String.Int>
并在 Swift String 的 stringByReplacingCharactersInRange
上使用它
func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
let existingString = textField.text ?? ""
let swiftRange = advance(existingString.startIndex, range.length)..<advance(existingString.startIndex, range.length) // I hate this.
let candidateString = existingString.stringByReplacingCharactersInRange(swiftRange, withString: string)
所以抛开生成 Swift 范围的代码不可读这一事实......这两种方法在执行上是否有所不同?具体来说,Swift 有更好的(可能更懂 unicode)版本的 stringByReplacingCharactersInRange
我通过避免转换为 NSString 得到了什么?
最佳答案
NSString
的
NSRange
相当于 String.UTF16.Index
的 Range
(又名 String .UTF16Index
)。
正确的方法(没有NSString
)是:
func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
let existingString = textField.text ?? ""
// convert `NSRange` to `Range<String.Index>`
let start = String.UTF16Index(range.location)
let end = start.advancedBy(range.length)
let swiftRange = start.samePositionIn(string)! ..< end.samePositionIn(string)!
let candidateString = existingString.stringByReplacingCharactersInRange(swiftRange, withString: string)
// Do validation...
return true
}
您可以扩展NSRange
:
extension NSRange {
func toStringRangeIn(string: String) -> Range<String.Index>? {
let start = String.UTF16Index(self.location)
let end = start.advancedBy(self.length)
if let start = start.samePositionIn(string), end = end.samePositionIn(string) {
return start ..< end
}
return nil
}
}
var str = "📅Hello 🇬🇧😀"
let range = NSMakeRange(8, 4)
str.stringByReplacingCharactersInRange(range.toStringRangeIn(str)!, withString: "FOO") // -> "📅Hello FOO😀"
(str as NSString).stringByReplacingCharactersInRange(range, withString: "FOO") // -> "📅Hello FOO😀"
有了这个,您可以:
func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
let existingString = textField.text ?? ""
let candidateString = existingString.stringByReplacingCharactersInRange(
range.toStringRangeIn(existingString)!,
withString: string
)
// Do validation...
return true
}
关于objective-c - NSString 和 Swift.String 上的 ReplaceCharactersInRange 之间有区别吗,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31695892/