Skip to content

Instantly share code, notes, and snippets.

@zwaldowski
Last active January 28, 2017 09:50
Show Gist options
  • Save zwaldowski/ed2a7c5f79c91d9ae226 to your computer and use it in GitHub Desktop.
Save zwaldowski/ed2a7c5f79c91d9ae226 to your computer and use it in GitHub Desktop.
Proper bridging for NSRegularExpression; Swift 1.2
import Foundation
// MARK: String
extension String {
func convert(#index: Int) -> Index? {
let utfIndex = advance(utf16.startIndex, index, utf16.endIndex)
return utfIndex.samePositionIn(self)
}
func convert(#index: String.Index) -> Int {
let utfIndex = index.samePositionIn(utf16)
return distance(utf16.startIndex, utfIndex)
}
public func convert(#range: NSRange) -> Range<Index>? {
if range.location == NSNotFound { return nil }
if let start = convert(index: range.location),
end = convert(index: NSMaxRange(range)) {
return start..<end
}
return nil
}
public func convert(#range: Range<String.Index>) -> NSRange {
let utfStart = convert(index: range.startIndex)
let utfEnd = convert(index: range.endIndex)
return NSRange(location: utfStart, length: distance(utfStart, utfEnd))
}
}
// MARK: NSRegularExpression
private func searchRange(string: String, range: Range<String.Index>?) -> NSRange {
return range.map { string.convert(range: $0) } ?? NSRange(location: 0, length: count(string.utf16))
}
public extension NSRegularExpression {
func matches(#string: String, options: NSMatchingOptions = nil, range: Range<String.Index>? = nil) -> [NSTextCheckingResult] {
return matchesInString(string, options: options, range: searchRange(string, range)) as! [NSTextCheckingResult]
}
func numberOfMatches(#string: String, options: NSMatchingOptions = nil, range: Range<String.Index>? = nil) -> Int {
return numberOfMatchesInString(string, options: options, range: searchRange(string, range))
}
func firstMatch(#string: String, options: NSMatchingOptions = nil, range: Range<String.Index>? = nil) -> NSTextCheckingResult? {
return firstMatchInString(string, options: options, range: searchRange(string, range))
}
func rangeOfFirstMatch(#string: String, options: NSMatchingOptions = nil, range: Range<String.Index>? = nil) -> Range<String.Index>? {
return string.convert(range: rangeOfFirstMatchInString(string, options: options, range: searchRange(string, range)))
}
}
// MARK: NSTextCheckingResult
public extension NSTextCheckingResult {
func firstRange(#string: String) -> Range<String.Index>? {
return string.convert(range: range)
}
subscript (idx: Int, string: String) -> Range<String.Index>? {
return string.convert(range: rangeAtIndex(idx))
}
func ranges(#string: String) -> LazyRandomAccessCollection<MapCollectionView<Range<Int>, Range<String.Index>>> {
return lazy(0..<numberOfRanges).map {
self[$0, string]!
}
}
}
// MARK: Demo
let s = "👹👀🐼📱"
let regex = NSRegularExpression(pattern: "🐼", options: nil, error: nil)!
// MARK: NSString
let ns = s as NSString
let nsRangeWhole = NSRange(location: 0, length: ns.length)
let nsRange = regex.rangeOfFirstMatchInString(s, options: nil, range: nsRangeWhole)
ns.substringWithRange(nsRange)
// MARK: Swift.String
if let range = regex.rangeOfFirstMatch(string: s) {
s[range]
}
if let result = regex.firstMatch(string: s) {
for range in result.ranges(string: s) {
s[range]
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment