使用(Swift)字符串提供给NSRange for NSRegularExpression的正确长度:参数是多少?



我对如何在 Swift 中使用NSRegularExpression类感到困惑,尤其是NSRange:length参数。

一些教程说NSRegularExpression应该只应用于NSString实例,而另一些教程说,只要你提供utf8.countutf16.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.IndexRange转换为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( 我们不再需要这样做的事实。

最新更新