为什么我无法通过使用“usedRectForTextContainer”来获取textContainer的矩形

我在这个问题中学到了NAlexN的答案( 在UILabel的NSAttributedString中创build可点击的“链接” ),并自己编写一个演示。 但是,对我来说,演示是不好的。 这里是我的代码:(每个人都可以直接复制下面的代码到一个新的项目来进行testing)

#import "ViewController.h" @interface ViewController () { UILabel* label; NSTextContainer *textContainer; NSLayoutManager *layoutManager; } @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; [super viewDidLoad]; label=[[UILabel alloc]initWithFrame:CGRectMake(15, 30, 350, 300)]; label.backgroundColor=[UIColor greenColor]; label.userInteractionEnabled = YES; UITapGestureRecognizer* tap=[[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(handleTapOnLabel:)]; [tap setNumberOfTapsRequired:1]; [label addGestureRecognizer:tap]; [self.view addSubview:label]; NSMutableAttributedString *attributedString =[[NSMutableAttributedString alloc] initWithString:@"String with a link" attributes:nil]; NSRange linkRange = NSMakeRange(14, 4); // for the word "link" in the string above NSDictionary *linkAttributes = @{ NSForegroundColorAttributeName : [UIColor colorWithRed:0.05 green:0.4 blue:0.65 alpha:1.0],NSUnderlineStyleAttributeName : @(NSUnderlineStyleSingle) }; [attributedString setAttributes:linkAttributes range:linkRange]; // Assign attributedText to UILabel label.attributedText = attributedString; // Create instances of NSLayoutManager, NSTextContainer and NSTextStorage layoutManager = [[NSLayoutManager alloc] init]; textContainer = [[NSTextContainer alloc] initWithSize:CGSizeZero]; NSTextStorage *textStorage = [[NSTextStorage alloc] initWithAttributedString:attributedString]; // Configure layoutManager and textStorage [layoutManager addTextContainer:textContainer]; [textStorage addLayoutManager:layoutManager]; // Configure textContainer 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 = label.bounds.size; NSLog(@"textContainer.size=%@",NSStringFromCGSize(textContainer.size)); } - (void)handleTapOnLabel:(UITapGestureRecognizer *)tapGesture { NSLog(@"Tap received"); CGPoint locationOfTouchInLabel = [tapGesture locationInView:tapGesture.view]; CGSize labelSize = tapGesture.view.bounds.size; CGRect textBoundingBox = [layoutManager usedRectForTextContainer:textContainer]; NSLog(@"textBoundingBox=%@",NSStringFromCGRect(textBoundingBox)); 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); // it's better to save the range somewhere when it was originally used for marking link in attributed string 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/"]]; NSLog(@" Link was taped "); } } @end 

运行的结果是:

2016-03-11 10:58:04.457 [13451:1007618] textContainer.size = {350,300}

2016-03-11 10:58:07.968 [13451:1007618]点击收到

2016-03-11 10:58:07.969 [13451:1007618] textBoundingBox = {{0,0},{0,0}}

从运行结果来看,layoutManager似乎不起作用。 我不明白为什么,也许我错误地使用了layoutManager。 任何机构可以帮助解决这个问题。 非常感谢!

PS:这个演示旨在在UILabel的NSAttributedText中创build一个可点击的url链接。

(OP的五年迟到了,但这可能对某个人有所帮助。)

这个问题可能是因为textBoundingBox的高度和宽度都是0。 尝试强制layoutManager预先正确布局文本,例如

 [layoutManager ensureLayoutForGlyphRange:NSMakeRange(0, attributedString.length)];