繁体   English   中英

NSLayoutManager characterIndexForPoint方法在iOS9上失败

[英]NSLayoutManager characterIndexForPoint method failing on ios9

我正在实现带有链接单击支持的自定义UILabel 为此,我有以下方法:一种用于初始化结构(仅调用一次),一种用于检测字符串中确定范围内的文本的单击:

- (void) sharedInit {
    // Remember, this method is only called once
    self.layoutManager = [[NSLayoutManager alloc] init];
    self.textContainer = [[NSTextContainer alloc] initWithSize:self.frame.size];
    [self.layoutManager addTextContainer:self.textContainer];
    self.myGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(onTap:)];

    self.textContainer.lineFragmentPadding = 0.0;
    self.textContainer.lineBreakMode = self.lineBreakMode;
    self.textContainer.maximumNumberOfLines = self.numberOfLines;
    self.textContainer.size = self.frame.size;
}

- (void) onTap:(UITapGestureRecognizer*) tapGesture {
    CGPoint location = [tapGesture locationInView:tapGesture.view];
    NSInteger index = [self.layoutManager characterIndexForPoint:locationOfTouchInLabel
                                                 inTextContainer:self.textContainer
                        fractionOfDistanceBetweenInsertionPoints:nil];

    NSLog(@"index of tapped character: %li", index);

    // ... and some more code to work with that index
}

- (void) setFrame:(CGRect)frame {
    [super setFrame:frame];
    self.textContainer.size = self.frame.size;
}

- (void) setAttributedText:(NSAttributedString *)attributedText {
    [super setAttributedText:attributedText];
    self.textStorage = [[NSTextStorage alloc] initWithAttributedString:attributedText];
    [self.textStorage addLayoutManager:self.layoutManager];
}

- (void) setNumberOfLines:(NSInteger)numberOfLines {
    [super setNumberOfLines:numberOfLines];
    self.textContainer.maximumNumberOfLines = numberOfLines;
}

此处的关键变量是indexonTap: mehtod)。 该变量返回被点击字符的索引,因此我们可以使用它。 这可以在iOS 8上完美运行,但是对于iOS 9,我看到了以下行为:

  • 如果标签只有一行,它将返回正确的索引
  • 如果标签有多行, 无论您在哪里单击, 它始终返回零

在开发iOS 8的功能时,我遇到了类似的问题,我通过将maximumNumberOfLinesNSTextContainer设置为正确的值来解决它,如您在初始化中所看到的。 当运行onTap方法时,TextContainer的配置参数(大小,maxNumOfLines等)正确。 我已经检查了文档( https://developer.apple.com/library/prerelease/ios/documentation/UIKit/Reference/NSTextContainer_Class_TextKit/index.html#//apple_ref/occ/instm/NSTextContainer/lineFragmentRectForProposedRect:atIndex:writingDirection :remainingRect :)显然在此版本中没有任何变化,所以我很迷路。 到目前为止,这似乎是一个iOS9错误,但我不想放弃任何选项。 我也提供了一些解决方法,但是如果可能的话,我想知道该方法的作用。

那么,有人知道发生了什么吗? 提前致谢...

编辑:

两件事情:

  • 我尝试咨询glyphIndex而不是charIndex ,到目前为止,它返回的结果相同(好一行,零行以上)
  • 我注意到结果不正确时, firstUnlaidCharIndex等于0。 在正常工作的情况下(iOS8和iOS9仅使用一行),它会返回正确的值,第一个越界字符。

尝试使用相同的UILabel宽度和CGFLOAT_MAX高度初始化NSTextContainer的大小

    self.textContainer.size = CGSizeMake(self.bounds.size.width, CGFLOAT_MAX);

解决了! 看起来问题出在setAttributedText:重载。 每当您更改标签的文本时,都会重新创建TextStorage,看起来布局管理器根本不喜欢它。 重用textStorage并通过调用setAttributedString:仅更改文本setAttributedString:解决了该问题。

实际上,我很早以前就解决了这个问题:((我编辑了帖子,但忘了回答自己。对不起!

暂无
暂无

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

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