Touchable text in NSMutableAttributedString
Do you want some text clickable in your text string? That's easy using iOS7/8, NSMutableAttributedString and the UITextView control!
1- Set text into the UITextView. Clickable texts must be a custom attribute;
//ViewDidLoad NSMutableParagraphStyle *paragraph = [[NSMutableParagraphStyle alloc] init]; paragraph.alignment = NSTextAlignmentJustified; paragraph.lineSpacing = 3; NSMutableAttributedString* agreeAttributedString = [[NSMutableAttributedString alloc] initWithString:@"You confirm you read our {0} and our {1}" attributes:@{ NSForegroundColorAttributeName : [UIColor blackColor]}]; NSAttributedString* termsAttributedString = [[NSAttributedString alloc] initWithString:@"Terms" attributes:@{ @"termsTag" : @(YES), NSForegroundColorAttributeName : [UIColor redColor]}]; NSAttributedString* policyAttributedString = [[NSAttributedString alloc] initWithString:localize:@"Policy" attributes:@{ @"policyTag" : @(YES), NSForegroundColorAttributeName : [UIColor greenColor]}]; NSRange range0 = [[agreeAttributedString string] rangeOfString:@"{0}"]; if(range0.location != NSNotFound) [agreeAttributedString replaceCharactersInRange:range0 withAttributedString:termsAttributedString]; NSRange range1 = [[agreeAttributedString string] rangeOfString:@"{1}"]; if(range1.location != NSNotFound) [agreeAttributedString replaceCharactersInRange:range1 withAttributedString:policyAttributedString]; [agreeAttributedString addAttribute:NSParagraphStyleAttributeName value:paragraph range:NSMakeRange(0, [agreeAttributedString length])]; self.txvText.attributedText = agreeAttributedString;
2- Add gesture tap to the UITextView
//ViewDidLoad UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(txvTextTouched:)]; [self.txvText addGestureRecognizer:tap];
3- Recognize the tap, find the character that's been tapped and check its attributes
-(void)txvTextTouched:(UITapGestureRecognizer *)recognizer { UITextView *textView = (UITextView *)recognizer.view; NSLayoutManager *layoutManager = textView.layoutManager; CGPoint location = [recognizer locationInView:textView]; location.x -= textView.textContainerInset.left; location.y -= textView.textContainerInset.top; NSUInteger characterIndex; characterIndex = [layoutManager characterIndexForPoint:location inTextContainer:textView.textContainer fractionOfDistanceBetweenInsertionPoints:NULL]; if (characterIndex < textView.textStorage.length) { NSRange range0; NSRange range1; id termsValue = [textView.textStorage attribute:@"termsTag" atIndex:characterIndex effectiveRange:&range0]; id policyValue = [textView.textStorage attribute:@"policyTag" atIndex:characterIndex effectiveRange:&range1]; if(termsValue) { NSLog(@"TERMS TAPPED"); return; } if(policyValue) { NSLog(@"POLICY TAPPED"); return; } } }
That's all!
NSLog(@"%@, %lu, %lu", termsValue, (unsigned long)range0.location, (unsigned long)range0.length);

















