[英]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; }
此处的关键变量是index
( onTap:
mehtod)。 该变量返回被点击字符的索引,因此我们可以使用它。 这可以在iOS 8上完美运行,但是对于iOS 9,我看到了以下行为:
在开发iOS 8的功能时,我遇到了类似的问题,我通过将maximumNumberOfLines
的NSTextContainer
设置为正确的值来解决它,如您在初始化中所看到的。 当运行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.