How to convert Range to NSRange?

I am updating my code in swift 3. We get an error while converting Range to NSRange. How to do it in fast 3?

func nsRange(_ range : Range<String.Index>) -> NSRange { let utf16from = String.UTF16View.Index(range.lowerBound, within: utf16) let utf16to = String.UTF16View.Index(range.upperBound, within: utf16) return NSRange(location: utf16.startIndex.distanceTo(utf16from), length: utf16from.distanceTo(utf16to)) } 
+21
swift
source share
2 answers

Xcode 10.2 β€’ Swift 5

 extension StringProtocol { func nsRange(from range: Range<Index>) -> NSRange { return .init(range, in: self) } } 

 let string = "Hello USA πŸ‡ΊπŸ‡Έ !!! Hello World !!!" if let range = string.range(of: "Hello World") { let nsRange = string.nsRange(from: range) (string as NSString).substring(with: nsRange) // "Hello World" } 

You can also create the corresponding nsRange(of:) extending StringProtocol :

 extension StringProtocol { func nsRange(of string: Self, options: String.CompareOptions = [], range: Range<Index>? = nil, locale: Locale? = nil) -> NSRange? { guard let range = self.range(of: string, options: options, range: range ?? startIndex..<endIndex, locale: locale ?? .current) else { return nil } return .init(range, in: self) } func nsRanges(of string: Self, 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(.init(range, in: self)) start = range.upperBound } 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" 
+63
source share

First of all, I would like to say a big thank you to the author of this subject, some time ago I used his solution for Swift 3. (I already increased his reputation)

but I would suggest a specialized extension for the range itself

in Swift 4

 extension Range where Bound == String.Index { var nsRange:NSRange { return NSRange(location: self.lowerBound.encodedOffset, length: self.upperBound.encodedOffset - self.lowerBound.encodedOffset) } } 

in this case, the previous sample may look like

 let string = "Hello USA πŸ‡ΊπŸ‡Έ !!! Hello World !!!" if let nsrange = string.range(of: "Hello World")?.nsRange { (string as NSString).substring(with: nsrange) // "Hello World" } 
+1
source share