Just as in Swift extract regex matches , a possible solution is to convert the given Swift String to NSString and apply the NSRange returned by enumerateMatchesInString() to this NSString :
class func addLinkAttribute(pattern: String, toText text: String, withAttributeName attributeName : String, toAttributedString attributedString :NSMutableAttributedString, withLinkAttributes linkAttributes: [NSObject : AnyObject]) { let nsText = text as NSString var error: NSError? if let regex = NSRegularExpression(pattern: pattern, options:.CaseInsensitive, error: &error) { regex.enumerateMatchesInString(text, options: .allZeros, range: NSMakeRange(0, nsText.length)) { result, _, _ in let range = result.range let foundText = nsText.substringWithRange(range) var linkAttributesWithName = linkAttributes linkAttributesWithName[attributeName] = foundText attributedString.addAttributes(linkAttributesWithName, range: range) } } }
(Alternative solution.) You can convert NSRange to Range<String.Index> without intermediate conversion to NSString . Via
extension String { func rangeFromNSRange(nsRange : NSRange) -> Range<String.Index>? { let utf16start = self.utf16.startIndex if let from = String.Index(self.utf16.startIndex + nsRange.location, within: self), let to = String.Index(self.utf16.startIndex + nsRange.location + nsRange.length, within: self) { return from ..< to } return nil } }
from fooobar.com/questions/22448 / ... , your code can be written as
class func addLinkAttribute(pattern: String, toText text: String, withAttributeName attributeName : String, toAttributedString attributedString :NSMutableAttributedString, withLinkAttributes linkAttributes: [NSObject : AnyObject]) { var error: NSError? if let regex = NSRegularExpression(pattern: pattern, options:.CaseInsensitive, error: &error) { regex.enumerateMatchesInString(text, options: .allZeros, range: NSMakeRange(0, count(text.utf16))) { result, _, _ in let nsRange = result.range if let strRange = text.rangeFromNSRange(nsRange) { let foundText = text.substringWithRange(strRange) var linkAttributesWithName = linkAttributes linkAttributesWithName[attributeName] = foundText attributedString.addAttributes(linkAttributesWithName, range: nsRange) } } } }
and this should also work correctly for all types of extended grapheme clusters (Emojis, regional indicators, etc.)