CTRun及CTRunGetPositions相关崩溃问题:不同iOS版本阈值差异咨询
问题原因与解决方案
崩溃根源
你的代码调用CTRunGetPositions时存在核心错误:
- 在Core Text的语义中,
CFRange(location: 0, length: 0)表示获取从位置0到run末尾的所有字形位置,而非单个位置。 - 你仅分配了单个
CGPoint的内存(var truncationPosition = CGPoint.zero),当truncationRun的字形数量超过1时,CTRunGetPositions会向该指针后方的内存写入数据,直接造成内存越界写入,破坏栈上的其他数据。
这种越界不会立刻触发崩溃,而是等到函数执行结束、栈帧销毁时才暴露。不同iOS系统阈值有差异,是因为各系统的栈布局、内存保护机制严格程度不同,对越界写入的容忍度存在区别。
修复方案
需根据truncationRun的实际字形数量,分配足够空间存储位置数据。以下两种方案可根据你的需求选择:
方案1:仅获取第一个字形的位置(匹配原代码意图)
func testFunc() { // ...... let runs = CTLineGetGlyphRuns(finalLine) as! [CTRun] if let truncationRun = runs.last { var truncationPosition = CGPoint.zero // 指定length为1,仅获取第一个字形的位置 CTRunGetPositions(truncationRun, CFRange(location: 0, length: 1), &truncationPosition) var truncationAscent: CGFloat = 0, truncationDescent: CGFloat = 0 let truncationWidth = CTRunGetTypographicBounds(truncationRun, CFRange(location: 0, length: 0), &truncationAscent, &truncationDescent, nil) // ...... } // ...... }
方案2:获取所有字形的位置
func testFunc() { // ...... let runs = CTLineGetGlyphRuns(finalLine) as! [CTRun] if let truncationRun = runs.last { let glyphCount = CTRunGetGlyphCount(truncationRun) // 分配对应数量的CGPoint数组 var positions = Array(repeating: CGPoint.zero, count: glyphCount) CTRunGetPositions(truncationRun, CFRange(location: 0, length: 0), &positions) var truncationAscent: CGFloat = 0, truncationDescent: CGFloat = 0 let truncationWidth = CTRunGetTypographicBounds(truncationRun, CFRange(location: 0, length: 0), &truncationAscent, &truncationDescent, nil) // ...... } // ...... }
补充说明
CTRunGetTypographicBounds使用CFRange(location:0, length:0)是合理的,该函数在length为0时会返回整个run的排版边界,仅通过指针返回单个数值,无需额外分配空间。
内容的提问来源于stack exchange,提问作者MangaK
相关产品推荐
相关产品推荐

