Created
August 29, 2016 20:27
-
-
Save sanekgusev/1fc00c66b6333044dffcb4a69416054e to your computer and use it in GitHub Desktop.
Convert an NSRange in NSString into a Range<String.Index>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//: Convert an NSRange from NSString into a Range<String.Index> | |
import Foundation | |
let swiftString: String = "🤖 This is an über-👍 string" | |
let swiftStringCharCount = swiftString.characters.count | |
let nsString = (swiftString as NSString).decomposedStringWithCanonicalMapping as NSString | |
let nsStringLength = nsString.length | |
let invalidNsRange: NSRange = NSMakeRange(1, 2) | |
let validNsRange: NSRange = NSMakeRange(20, 2) | |
let invalidNsSubstring: NSString = nsString.substring(with: invalidNsRange) as NSString | |
let validNsSubstring: NSString = nsString.substring(with: validNsRange) as NSString | |
func characterRangeFrom(nsRange: NSRange, nsString: NSString) -> Range<String.Index>? { | |
let swiftString: String = nsString.precomposedStringWithCanonicalMapping as String | |
var lowerBound: String.Index? = nil | |
var upperBound = swiftString.startIndex | |
var lowerBoundValid = false | |
var upperBoundValid = false | |
nsString.enumerateSubstrings(in: NSRange(location: 0, length: nsRange.location + nsRange.length), | |
options: .byComposedCharacterSequences) { (substring, substringRange, enclosingRange, stop) in | |
if substringRange.location <= nsRange.location { | |
lowerBound = lowerBound == nil ? swiftString.startIndex : swiftString.index(after: lowerBound!) | |
if substringRange.location == nsRange.location { | |
lowerBoundValid = true | |
} | |
} | |
if substringRange.location + substringRange.length <= nsRange.location + nsRange.length { | |
upperBound = swiftString.index(after: upperBound) | |
if substringRange.location + substringRange.length == nsRange.location + nsRange.length { | |
upperBoundValid = true | |
} | |
} | |
} | |
guard lowerBoundValid && upperBoundValid else { | |
return nil | |
} | |
return Range(uncheckedBounds: (lowerBound!, upperBound)) | |
} | |
if let validRange = characterRangeFrom(nsRange: validNsRange, nsString: nsString) { | |
let validSubstring = swiftString[validRange] | |
} | |
if let invalidRange = characterRangeFrom(nsRange: invalidNsRange, nsString: nsString) { | |
let invalidSubstring = swiftString[invalidRange] | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment