如何在 Objective-C 中单击 UILabel 上的超链接打开视图控制器

How to open a view controller on click of hyperlink on UILabel in Objective-C

我必须在 UILabel 上通过 hyperlink 打开一个视图控制器。 This 对我来说只起到了一半的作用。根据我的项目要求,我无法使用 UITextView

以下代码在 UILabel 上创建一个 hyperlink 并检测 link 上的触摸,但我想打开一个视图控制器而不是 URL。

@property (weak, nonatomic) @IBOutlet UILabel *label;
NSLayoutManager *layoutManager;
NSTextContainer *textContainer;
NSTextStorage *textStorage;

UILabel:

上创建 hyperlink
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;

// 检测此 Hyperlink.

上的触摸
_label.userInteractionEnabled = YES;
[_label addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTapOnLabel:)]];

要找出点击的是 link,而不是标签的任何其他部分。

// 创建 NSLayoutManager、NSTextContainer 和 NSTextStorage 的实例

layoutManager = [[NSLayoutManager alloc] init];
textContainer = [[NSTextContainer alloc] initWithSize:CGSizeZero];
textStorage = [[NSTextStorage alloc] initWithAttributedString:attributedString];

// 配置layoutManager、textStorage和textContainer

[layoutManager addTextContainer:textContainer];

[textStorage addLayoutManager:layoutManager];

textContainer.lineFragmentPadding = 0.0;
textContainer.lineBreakMode = _label.lineBreakMode;
textContainer.maximumNumberOfLines =_label.numberOfLines;

// 每次标签更改其框架时,更新 textContainer 的大小:

- (void)viewDidLayoutSubviews
{
    [super viewDidLayoutSubviews];
    textContainer.size = self.label.bounds.size;
}

//检测点击是否正好在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://whosebug.com/"]];
    }
}

// 使用这个函数呈现newViewController

-(void)navigateToTATViewController{
    TATViewController *tatVC = [[self getStoryboardWithStoryboardType: kListingStoryboard] instantiateViewControllerWithIdentifier: @"TATViewControllerID"];
    [self.navigationController presentViewController: tatVC animated:true completion:nil];
}

所以基本上你需要更新行:

[[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"https://whosebug.com/"]];

并将其替换为 [self navigateToTATViewController];