如何从完整字符串 iOS swift 中查找字符串的多个 NSRange
How to find Multiple NSRange for a string from full string iOS swift
let fullString = "Hello world, there are \(string(07)) continents and \(string(195)) countries."
let range = [NSMakeRange(24,2), NSMakeRange(40,3)]
需要在整个完整字符串中找到数字的 NSRange,并且两个数字有可能相同。目前硬编码如上所示,消息可以是动态的,其中硬编码值会出现问题。
我已拆分字符串并尝试获取 NSRange
,因为可能存在相同的值。像 stringOne 和 stringTwo。
func findNSMakeRange(initialString:String, fromString: String) {
let fullStringRange = fromString.startIndex..<fromString.endIndex
fromString.enumerateSubstrings(in: fullStringRange, options: NSString.EnumerationOptions.byWords) { (substring, substringRange, enclosingRange, stop) -> () in
let start = distance(fromString.startIndex, substringRange.startIndex)
let length = distance(substringRange.startIndex, substringRange.endIndex)
let range = NSMakeRange(start, length)
if (substring == initialString) {
print(substring, range)
}
})
}
收到类似 Cannot invoke distance with an argument list of type (String.Index, String.Index)
的错误
谁有更好的解决方案?
您说您想要遍历字符串中的 NSRange
个匹配项,以便您可以将粗体属性应用于相关的子字符串。您可以使用 NSRegularExpression
来做到这一点:
let range = NSRange(location: 0, length: string.count)
try! NSRegularExpression(pattern: "[0-9]+").enumerateMatches(in: string, range: range) { result, _, _ in
guard let range = result?.range else { return }
attributedString.setAttributes(boldAttributes, range: range)
}
就我个人而言,我发现有一个方法可以 return 一个 Swift 范围的数组,即 [Range<String.Index>]
:
extension StringProtocol {
func ranges<T: StringProtocol>(of string: T, options: String.CompareOptions = []) -> [Range<Index>] {
var ranges: [Range<Index>] = []
var start: Index = startIndex
while let range = range(of: string, options: options, range: start ..< endIndex) {
ranges.append(range)
if !range.isEmpty {
start = range.upperBound // if not empty, resume search at upper bound
} else if range.lowerBound < endIndex {
start = index(after: range.lowerBound) // if empty and not at end, resume search at next character
} else {
break // if empty and at end, then quit
}
}
return ranges
}
}
然后就可以这样使用了:
let string = "Hello world, there are 09 continents and 195 countries."
let ranges = string.ranges(of: "[0-9]+", options: .regularExpression)
然后你可以 map
Range
到 NSRange
。回到最初的例子,如果你想让这些数字在一些属性字符串中加粗:
string.ranges(of: "[0-9]+", options: .regularExpression)
.map { NSRange([=13=], in: string) }
.forEach { attributedString.setAttributes(boldAttributes, range: [=13=]) }
let fullString = "Hello world, there are \(string(07)) continents and \(string(195)) countries."
let range = [NSMakeRange(24,2), NSMakeRange(40,3)]
需要在整个完整字符串中找到数字的 NSRange,并且两个数字有可能相同。目前硬编码如上所示,消息可以是动态的,其中硬编码值会出现问题。
我已拆分字符串并尝试获取 NSRange
,因为可能存在相同的值。像 stringOne 和 stringTwo。
func findNSMakeRange(initialString:String, fromString: String) {
let fullStringRange = fromString.startIndex..<fromString.endIndex
fromString.enumerateSubstrings(in: fullStringRange, options: NSString.EnumerationOptions.byWords) { (substring, substringRange, enclosingRange, stop) -> () in
let start = distance(fromString.startIndex, substringRange.startIndex)
let length = distance(substringRange.startIndex, substringRange.endIndex)
let range = NSMakeRange(start, length)
if (substring == initialString) {
print(substring, range)
}
})
}
收到类似 Cannot invoke distance with an argument list of type (String.Index, String.Index)
谁有更好的解决方案?
您说您想要遍历字符串中的 NSRange
个匹配项,以便您可以将粗体属性应用于相关的子字符串。您可以使用 NSRegularExpression
来做到这一点:
let range = NSRange(location: 0, length: string.count)
try! NSRegularExpression(pattern: "[0-9]+").enumerateMatches(in: string, range: range) { result, _, _ in
guard let range = result?.range else { return }
attributedString.setAttributes(boldAttributes, range: range)
}
就我个人而言,我发现有一个方法可以 return 一个 Swift 范围的数组,即 [Range<String.Index>]
:
extension StringProtocol {
func ranges<T: StringProtocol>(of string: T, options: String.CompareOptions = []) -> [Range<Index>] {
var ranges: [Range<Index>] = []
var start: Index = startIndex
while let range = range(of: string, options: options, range: start ..< endIndex) {
ranges.append(range)
if !range.isEmpty {
start = range.upperBound // if not empty, resume search at upper bound
} else if range.lowerBound < endIndex {
start = index(after: range.lowerBound) // if empty and not at end, resume search at next character
} else {
break // if empty and at end, then quit
}
}
return ranges
}
}
然后就可以这样使用了:
let string = "Hello world, there are 09 continents and 195 countries."
let ranges = string.ranges(of: "[0-9]+", options: .regularExpression)
然后你可以 map
Range
到 NSRange
。回到最初的例子,如果你想让这些数字在一些属性字符串中加粗:
string.ranges(of: "[0-9]+", options: .regularExpression)
.map { NSRange([=13=], in: string) }
.forEach { attributedString.setAttributes(boldAttributes, range: [=13=]) }