我正在为UITextField编写验证器,我给出了现有的字符串,替换字符串和替换发生的NSRange。我有两个版本的代码来获取新的候选字符串:
一个。明确使用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
}
湾生成Range<String.Int>
并在Swift String&#39; s 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得到它?
答案 0 :(得分:2)
NSRange
的{p> NSString
相当于Range
的{{1}}(又名String.UTF16.Index
)。
正确的方式(没有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"
答案 1 :(得分:0)
是。两种方法之间存在差异,第二种方法更为正确。它还可以正确处理多代码字符:
var str = "Hello , playground"
let range = NSMakeRange(0, 8)
let swiftRange = advance(str.startIndex, range.location)..<advance(str.startIndex, range.length) // I hate this.
var newString = str.stringByReplacingCharactersInRange(swiftRange, withString: "goodbye")
// => goodbye playground
newString = (str as NSString).stringByReplacingCharactersInRange(range, withString: "goodbye")
// => "goodbye, playground"
我假设这是因为范围计算得更好,而不是因为替换方法有不同的实现。 swiftRange是0..<15