layoutManager boundingRectForGlyphRange:inTextContainer:不适用于所有字符串 [英] layoutManager boundingRectForGlyphRange:inTextContainer: does not work for all strings

查看:60
本文介绍了layoutManager boundingRectForGlyphRange:inTextContainer:不适用于所有字符串的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个UILabel,带有类似字符串的推文,包括其他用户的提及.

I have a UILabel with a tweet like string, including mentions of other users.

Hey @stephen and @frank and @Jason1.

我正在尝试使每个提及都可以点击,以便我可以加载该用户的个人资料.我从另一篇SO帖子中找到了一些代码(

I am attempting to have each mention be tappable so I can load that user's profile. I found some code from another SO post (How do I locate the CGRect for a substring of text in a UILabel?) that I was able to use in order to locate the position of each mention in the string. However it usually doesn't work for the last or last 2 mentions in a post.

SO帖子中的方法(稍作修改):

The method from the SO post (slightly modified):

- (CGRect)boundingRectForCharacterRange:(NSRange)range
{
    NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithAttributedString:self.myLabel.attributedText];
    NSTextStorage *textStorage = [[NSTextStorage alloc] initWithAttributedString:attributedString];
    NSLayoutManager *layoutManager = [[NSLayoutManager alloc] init];
    [textStorage addLayoutManager:layoutManager];
    NSTextContainer *textContainer = [[NSTextContainer alloc] initWithSize:self.myLabel.bounds.size];
    textContainer.lineFragmentPadding = 0;
    [layoutManager addTextContainer:textContainer];

    NSRange glyphRange;

    // Convert the range for glyphs.
    [layoutManager characterRangeForGlyphRange:range actualGlyphRange:&glyphRange];

    return [layoutManager boundingRectForGlyphRange:glyphRange inTextContainer:textContainer];
}

然后,在 touchesEnded:中,我遍历每个提及内容,获取主字符串中的范围,并检查触摸是否在该CGRect内部.

Then, in touchesEnded:, I loop over each mention, get the range in the main string, and check if the touch is inside that CGRect.

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{        
    UITouch *touch = touches.allObjects[0];

    for (NSString *mention in self.mentions) {
        NSRange range = [self.postText rangeOfString:mention options:NSCaseInsensitiveSearch];
        CGRect rect = [self boundingRectForCharacterRange:range];
        NSLog(@"rect for %@ is %@", mention, NSStringFromCGRect(rect));
    }
}

// Output from above
rect for @stephen is {{33.388, 0}, {72.471001, 20.553001}}
rect for @frank is {{143.021, 0}, {49.809998, 20.553001}}
rect for @Jason1 is {{0, 0}, {0, 0}}

这在大多数情况下都有效,但是@ Jason1没有匹配.我已经切换了名称的顺序,并且始终是最后一个.我的标签确实会自动换行,但有时仍会与第二行和第三行上的名称匹配.是否有设置或我缺少的东西?我试过更改标签的大小和字体,但是没有运气.我在这里真是茫然.

And this works great most of the time, however @Jason1 does not get matched. I've switched the order of the names and it's always the last one. My label does wrap, but it still sometimes matches names on the 2nd and 3rd lines. Is there a setting or something I'm missing? I've tried changing the size and font of the labels but no luck. I'm at a real loss here.

推荐答案

此问题的解决方法是在初始化NSTextContainer时不设置高度约束.改用非常大的数字.

The fix for this is not to set the height constraint when initializing the NSTextContainer. Use a very large number instead.

NSTextContainer *textContainer = [[NSTextContainer alloc] initWithSize:CGSizeMake(self.myLabel.bounds.size.width, CGFLOAT_MAX)];

这篇关于layoutManager boundingRectForGlyphRange:inTextContainer:不适用于所有字符串的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆