I have to open a view controller via a hyperlink on a UILabel
. This only worked halfway for me. I cannot use UITextView
according to my project requirement.
The following code creates a hyperlink on a UILabel
and detects touch on the link but I want to open a view controller instead of an URL.
@property (weak, nonatomic) @IBOutlet UILabel *label;
NSLayoutManager *layoutManager;
NSTextContainer *textContainer;
NSTextStorage *textStorage;
Create hyperlink on a UILabel
:
NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithString:@"String with a link" attributes:nil];
NSRange linkRange = NSMakeRange(14, 4);
NSDictionary *linkAttributes = @{ NSForegroundColorAttributeName : [UIColor colorWithRed:0.05 green:0.4 blue:0.65 alpha:1.0],
NSUnderlineStyleAttributeName : @(NSUnderlineStyleSingle) };
[attributedString setAttributes:linkAttributes range:linkRange];
_label.attributedText = attributedString;
// To detect touches on this Hyperlink.
_label.userInteractionEnabled = YES;
[_label addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTapOnLabel:)]];
To Find out tap was on link, not on any other portion of the label.
// Create instances of NSLayoutManager, NSTextContainer and NSTextStorage
layoutManager = [[NSLayoutManager alloc] init];
textContainer = [[NSTextContainer alloc] initWithSize:CGSizeZero];
textStorage = [[NSTextStorage alloc] initWithAttributedString:attributedString];
// Configure layoutManager, textStorage and textContainer
[layoutManager addTextContainer:textContainer];
[textStorage addLayoutManager:layoutManager];
textContainer.lineFragmentPadding = 0.0;
textContainer.lineBreakMode = _label.lineBreakMode;
textContainer.maximumNumberOfLines =_label.numberOfLines;
// each time the label changes its frame, update textContainer's size:
- (void)viewDidLayoutSubviews
{
[super viewDidLayoutSubviews];
textContainer.size = self.label.bounds.size;
}
// detect whether the tap was exactly on the link:
- (void)handleTapOnLabel:(UITapGestureRecognizer *)tapGesture
{
CGPoint locationOfTouchInLabel = [tapGesture locationInView:tapGesture.view];
CGSize labelSize = tapGesture.view.bounds.size;
CGRect textBoundingBox = [layoutManager usedRectForTextContainer:textContainer];
CGPoint textContainerOffset = CGPointMake((labelSize.width - textBoundingBox.size.width) * 0.5 - textBoundingBox.origin.x,
(labelSize.height - textBoundingBox.size.height) * 0.5 - textBoundingBox.origin.y);
CGPoint locationOfTouchInTextContainer = CGPointMake(locationOfTouchInLabel.x - textContainerOffset.x,
locationOfTouchInLabel.y - textContainerOffset.y);
NSInteger indexOfCharacter = [layoutManager characterIndexForPoint:locationOfTouchInTextContainer
inTextContainer:textContainer
fractionOfDistanceBetweenInsertionPoints:nil];
NSRange linkRange = NSMakeRange(14, 4);
if (NSLocationInRange(indexOfCharacter, linkRange)) {
// Open an URL, or handle the tap on the link in any other way
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"https://stackoverflow.com/"]];
}
}
// using this function to present newViewController
-(void)navigateToTATViewController{
TATViewController *tatVC = [[self getStoryboardWithStoryboardType: kListingStoryboard] instantiateViewControllerWithIdentifier: @"TATViewControllerID"];
[self.navigationController presentViewController: tatVC animated:true completion:nil];
}
CodePudding user response:
So basically you need to update the line:
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"https://stackoverflow.com/"]];
and replace it with [self navigateToTATViewController]
;