diff --git a/KILabel/Source/KILabel.h b/KILabel/Source/KILabel.h index 293792f..25ad067 100644 --- a/KILabel/Source/KILabel.h +++ b/KILabel/Source/KILabel.h @@ -308,6 +308,15 @@ IB_DESIGNABLE */ + (instancetype)linkClassifierWithRegex:(NSRegularExpression *)regex; +/** + * Create a new instance of KILabelLinkClassifier that will use the given regex for classifying and NSLinkAttributeName attribute + * + * @param regex Regex used to match strings for links + * + * @return Instance of KILabelLinkClassifier + */ ++ (instancetype)linkClassifierWithLinkAndRegex:(NSRegularExpression *)regex; + /** * Helper method for extracting the string to use as the "link" from an attributed string. The * plain text matching the range will be used, unless an NSLinkAttributedName property is present. diff --git a/KILabel/Source/KILabel.m b/KILabel/Source/KILabel.m index b32b882..a227f69 100644 --- a/KILabel/Source/KILabel.m +++ b/KILabel/Source/KILabel.m @@ -65,6 +65,7 @@ @implementation KILabel KILabelLinkClassifier *_userHandleClassifier; KILabelLinkClassifier *_hashtagClassifier; KILabelLinkClassifier *_urlClassifier; + NSDictionary *touchedLink; } #pragma mark - Construction @@ -145,7 +146,7 @@ - (void)setupLinkClassifiers // Use a data detector to find urls in the text NSError *error = nil; NSDataDetector *detector = [[NSDataDetector alloc] initWithTypes:NSTextCheckingTypeLink error:&error]; - _urlClassifier = [KILabelLinkClassifier linkClassifierWithRegex:detector]; + _urlClassifier = [KILabelLinkClassifier linkClassifierWithLinkAndRegex:detector]; // Make sure the required link classifiers are attached [self updateDefaultLinkClassifiers]; @@ -393,6 +394,11 @@ - (void)setText:(NSString *)text - (void)setAttributedText:(NSAttributedString *)attributedText { + if(!attributedText) + { + attributedText = [[NSAttributedString alloc] initWithString:@"" attributes:[self attributesFromProperties]]; + } + // Pass the text to the super class first [super setAttributedText:attributedText]; @@ -722,7 +728,6 @@ - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event _isTouchMoved = NO; // Get the info for the touched link if there is one - NSDictionary *touchedLink; CGPoint touchLocation = [[touches anyObject] locationInView:self]; touchedLink = [self linkAtPoint:touchLocation]; @@ -756,10 +761,8 @@ - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event } // Get the info for the touched link if there is one - NSDictionary *touchedLink; CGPoint touchLocation = [[touches anyObject] locationInView:self]; - touchedLink = [self linkAtPoint:touchLocation]; - + if (touchedLink) { NSRange range = [[touchedLink objectForKey:KILabelRangeKey] rangeValue]; @@ -844,6 +847,65 @@ - (instancetype)initWithClassifier:(KILinkClassifier)classifier return self; } ++ (instancetype)linkClassifierWithLinkAndRegex:(NSRegularExpression *)regex +{ + KILabelLinkClassifier *classifier = [[KILabelLinkClassifier alloc] initWithClassifier:^NSArray *(KILabel *label) { + NSMutableArray *rangesForUserHandles = [[NSMutableArray alloc] init]; + + // We run the regex on the label's plain text + NSString *text = label.text; + + // Run the expression and get matches + NSArray *matches = [regex matchesInString:text options:0 range:NSMakeRange(0, text.length)]; + + // Add all our ranges to the result + for (NSTextCheckingResult *match in matches) + { + NSRange matchRange = [match range]; + NSString *matchString = [KILabelLinkClassifier linkStringFromAttributedString:label.attributedText + withRange:matchRange]; + + // Add the link if its not in our ignore list + if (![label.ignoredKeywords containsObject:[matchString lowercaseString]]) + { + [rangesForUserHandles addObject:@{KILabelRangeKey : [NSValue valueWithRange:matchRange], + KILabelLinkKey : matchString + }]; + } + } + + // check for NSLinkAttributeName too + + [label.attributedText enumerateAttribute:NSLinkAttributeName + inRange:NSMakeRange(0, label.attributedText.length) + options:0 + usingBlock:^(id value, NSRange range, BOOL *stop) { + + if(!value) + { + return; + } + + NSRange matchRange = range; + NSString *matchString = [KILabelLinkClassifier linkStringFromAttributedString:label.attributedText + withRange:matchRange]; + + // Add the link if its not in our ignore list + if (![label.ignoredKeywords containsObject:[matchString lowercaseString]]) + { + [rangesForUserHandles addObject:@{KILabelRangeKey : [NSValue valueWithRange:matchRange], + KILabelLinkKey : matchString + }]; + } + }]; + + + return rangesForUserHandles; + }]; + + return classifier; +} + + (instancetype)linkClassifierWithRegex:(NSRegularExpression *)regex { KILabelLinkClassifier *classifier = [[KILabelLinkClassifier alloc] initWithClassifier:^NSArray *(KILabel *label) {