NSLayoutManager characterIndexForPoint方法在ios9上失败

Bar*_*erk 2 objective-c ios 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;
}

这里的关键变量是index(onTap:mehtod).该变量返回tapped字符的索引,以便我们可以使用它.这与iOS 8完美配合,但对于iOS 9,我看到以下行为:

  • 如果标签有一行,则返回正确的索引
  • 如果标签有多行,无论您在哪里点击,它总是返回零.

我遇到类似的问题时,我正在开发功能为iOS 8,和我解决它通过设置maximumNumberOfLinesNSTextContainer正确值,你可以在初始化看到.onTap运行该方法时,TextContainer的配置参数(size,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只有一行),它将返回正确的值,即第一个越界字符.

Exc*_*ion 6

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

    self.textContainer.size = CGSizeMake(self.bounds.size.width, CGFLOAT_MAX);
Run Code Online (Sandbox Code Playgroud)