我对如何在 Swift 中使用NSRegularExpression
类感到困惑,尤其是NSRange
的:length
参数。
一些教程说NSRegularExpression应该只应用于NSString实例,而另一些教程说,只要你提供utf8.count
或utf16.count
:length
参数NSRange
就可以将其应用于(Swift(字符串实例:
var str : String = "#tweak #wow #gaming"
if let regex = try? NSRegularExpression(pattern: "#[a-z0-9]+", options: .caseInsensitive) {
regex.matches(in: str, options: [], range: NSRange(location: 0, length: str.utf8.count)).map {
print(str.substring(with: $0.range))
}
}
以下是该来源的引述:
由于字符串在 Swift 中的处理方式不同,并且 Objective-C,你需要为 NSRange 实例提供一个 字符串长度来自 NSString,而不是来自字符串。
粗略地说,这是因为NSString使用固定宽度编码 和字符串使用可变宽度编码。
此外,以下文档真的是 Apple 在 Swift 中记录NSRegularExpression
类方面能做的最好的文档吗?
https://developer.apple.com/documentation/foundation/nsregularexpression
我至少期望该类的属性和方法列表,但它只显示一些示例。有没有更详细的文档?
utf16 计数是正确的,而不是 utf8 计数。或者,最好使用方便的初始值设定项,它将String.Index
的Range
转换为NSRange
:
let range = NSRange(str.startIndex..., in: str)
并将NSRange
转换为String.Range
:
let range = Range(nsRange, in: str)
因此,将其放在一起:
let str = "#tweak #wow #gaming"
if let regex = try? NSRegularExpression(pattern: "#[a-z0-9]+", options: .caseInsensitive) {
let nsRange = NSRange(str.startIndex..., in: str)
let strings = regex.matches(in: str, range: nsRange).compactMap {
Range($0.range, in: str).map { str[$0] }
}
print(strings)
}
参见 WWDC 2017 与框架的有效交互,其中讨论了 (a( 我们在处理范围时对 UTF16 的历史使用;以及 (b( 我们不再需要这样做的事实。