CTRunGetImageBounds在iOS 10及以下版本上返回不正确的x坐标

CTRunGetImageBounds在iOS 10及以下版本上返回不正确的x坐标,ios,core-text,Ios,Core Text,我正在使用CoreText,并试图在iOS 11/12上添加对自定义标签的链接支持,但我也需要支持较旧的软件版本。为此,我检查用户的触摸是否与链接文本边界相交 要获得边界,我只需调用CTRunGetImageBounds(run、context、CFRangeMake(0,0))。这在iOS 11和iOS 12上运行得很好,但在iOS 9和iOS 10上却被破坏了。在iOS 11上,我得到一个沿(250,8.1100,30)行的rect,但是在iOS 9上,相同的函数调用返回(0.1,8.110

我正在使用CoreText,并试图在iOS 11/12上添加对自定义标签的链接支持,但我也需要支持较旧的软件版本。为此,我检查用户的触摸是否与链接文本边界相交

要获得边界,我只需调用
CTRunGetImageBounds(run、context、CFRangeMake(0,0))
。这在iOS 11和iOS 12上运行得很好,但在iOS 9和iOS 10上却被破坏了。在iOS 11上,我得到一个沿(250,8.1100,30)行的rect,但是在iOS 9上,相同的函数调用返回(0.1,8.1100,30)。x坐标似乎相对于梯段,而不是实际帧。由于坐标无效,无法在iOS 9/10上正确单击链接,这显然是一个问题

我已经包括了一张比较这两者的图片。预期的行为是链接应该用绿色矩形突出显示。请注意,iOS 12模拟器可以正确执行此操作,而9.3由于接近零的x坐标,所有矩形都向左猛击

这可能是一个CoreText错误,也可能是苹果在没有记录的情况下改变了某些行为。在iOS 9上
CTRunGetImageBounds
返回相对于自身的x值,而不是更大的帧。这意味着,尽管高度和宽度都是正确的,但返回的x坐标毫无用处。由于这是一个长期的死固件,它不会得到修复,但我找到了一个工作,反正

斯威夫特4
///获取给定CTRun的CoreText相对帧。此方法适用于iOS CGRect{
让imageBounds=CTRunGetImageBounds(运行、上下文、CFRangeMake(0,0))
如果可用(iOS 11.0,*){
//未安装bug的iOS,可以假定边界是正确的
返回图像边界
}否则{
//
/// Get the CoreText relative frame for a given CTRun. This method works around an iOS <=10 CoreText bug in CTRunGetImageBounds
///
/// - Parameters:
///   - run: The run
///   - context: Context, used by CTRunGetImageBounds
/// - Returns: A tight fitting, CT rect that fits around the run
func getCTRectFor(run:CTRun,context:CGContext) -> CGRect {
    let imageBounds = CTRunGetImageBounds(run, context, CFRangeMake(0, 0))
    if #available(iOS 11.0, *) {
        //Non-bugged iOS, can assume the bounds are correct
        return imageBounds
    } else {
        //<=iOS 10 has a bug with getting the frame of a run where it gives invalid x positions
        //The CTRunGetPositionsPtr however works as expected and returns the correct position. We can take that value and substitute it
        let runPositionsPointer = CTRunGetPositionsPtr(run)
        if let runPosition = runPositionsPointer?.pointee {
            return CGRect.init(x: runPosition.x, y: imageBounds.origin.y, width: imageBounds.width, height: imageBounds.height)
        }else {
            //FAILED TO OBTAIN RUN ORIGIN? FALL BACK.
            return imageBounds
        }
    }
}