Xcode 11 โข Swift 5.1
import Foundation
extension RangeExpression where Bound == String.Index {
func nsRange<S: StringProtocol>(in string: S) -> NSRange { .init(self, in: string) }
}
let string = "Hello USA ๐บ๐ธ !!! Hello World !!!"
if let nsRange = string.range(of: "Hello World")?.nsRange(in: string) {
(string as NSString).substring(with: nsRange) // "Hello World"
}
You can also create the corresponding nsRange(of:)
method extending StringProtocol
:
extension StringProtocol {
func nsRange<S: StringProtocol>(of string: S, options: String.CompareOptions = [], range: Range<Index>? = nil, locale: Locale? = nil) -> NSRange? {
self.range(of: string,
options: options,
range: range ?? startIndex..<endIndex,
locale: locale ?? .current)?
.nsRange(in: self)
}
func nsRanges<S: StringProtocol>(of string: S, options: String.CompareOptions = [], range: Range<Index>? = nil, locale: Locale? = nil) -> [NSRange] {
var start = range?.lowerBound ?? startIndex
let end = range?.upperBound ?? endIndex
var ranges: [NSRange] = []
while start < end,
let range = self.range(of: string,
options: options,
range: start..<end,
locale: locale ?? .current) {
ranges.append(range.nsRange(in: self))
start = range.lowerBound < range.upperBound ? range.upperBound :
index(range.lowerBound, offsetBy: 1, limitedBy: endIndex) ?? endIndex
}
return ranges
}
}
let string = "Hello USA ๐บ๐ธ !!! Hello World !!!"
if let nsRange = string.nsRange(of: "Hello World") {
(string as NSString).substring(with: nsRange) // "Hello World"
}
let nsRanges = string.nsRanges(of: "Hello")
print(nsRanges) // "[{0, 5}, {19, 5}]\n"