ios - NSLayoutManager characterIndexForPoint 方法在 ios9 上失败

标签 ios objective-c 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 开发该功能时遇到了类似的问题,我通过将 NSTextContainermaximumNumberOfLines 设置为正确的值来解决它,就像您一样可以在初始化中看到。当 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);

关于ios - NSLayoutManager characterIndexForPoint 方法在 ios9 上失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32735575/

相关文章:

iphone - 根据纬度和经度得到错误的排序距离

ios - 为什么我更新的应用程序在启动时仅适用于 IOS8 崩溃?

ios - 如何从 PHAsset 获取原始图像和媒体类型?

ios - 如何从使用语言环境设置格式化的 NSString timeStyle 获取 NSDate

ios - UIWindow addSubview 在 iOS 9 中不起作用

ios - 尝试在异常 : _descendantWillPresentViewController 中呈现模态结果

ios - 如何使按钮在swift中从不同的场景调用方法

ios - 使用 NSMutableURLRequest 的字符串请求

ios - 如何在 Objective-C 中的上一个高度和下一个高度之间留出一些空间来制作随机高度?

iOS 9 新功能 Free Provisioning(在设备上运行您的应用程序,只需使用您的 Apple ID,无需 Apple 开发者成员(member)资格)