繁体   English   中英

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

[英]Why do I fail to get textContainer's rect by using “usedRectForTextContainer”

我在此问题( 在UILabel的NSAttributedString中创建可点击的“链接”? )中学会了NAlexN的答案,并亲自编写了一个演示。 但是,我无法进行演示。 这是我的代码:(每个人都可以将以下代码直接复制到新项目中进行测试)

#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中创建可点击的url链接。

(对于OP来说晚了五年,但这可能仍然对某人有所帮助。)

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

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

在您的代码中,textStorage将被释放。 因此,将TextStorage保留在您的ViewController中,可以正常工作。

@interface ViewController ()
{
    UILabel* label;

    NSTextContainer *textContainer;
    NSLayoutManager *layoutManager;
    NSTextStorage  *textStorage;
}
@end
....
// Create instances of NSLayoutManager, NSTextContainer and NSTextStorage
layoutManager = [[NSLayoutManager alloc] init];
textContainer = [[NSTextContainer alloc] initWithSize:CGSizeZero];
textStorage = [[NSTextStorage alloc] initWithAttributedString:attributedString];

// Configure layoutManager and textStorage
[layoutManager addTextContainer:textContainer];
[textStorage addLayoutManager:layoutManager];

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM