AttributedString icon indicating copy to clipboard operation
AttributedString copied to clipboard

$100美刀 有偿征集解决方案 TextKit与UILabel内容同步问题

Open lixiang1994 opened this issue 5 years ago • 10 comments


完美解决此问题, 以$100美刀作为酬谢, 支持 微信支付, 支付宝支付, PayPal支付.

  • 解决上述问题, 确保自测无误.
  • 提交PR或直接联系本人交付相关代码.
  • 本人验证通过测试.
  • 2小时内根据以上支付方式支付酬谢金.
  • Release记录 以示感谢🙏

描述:

本库对于 UILabel 的点击事件实现方案是使用 TextKit 构建一个与 UILabel 显示一致的内容, 通过TextKit计算出所点击的字符.

问题:

由于UILabel的特殊性, 导致TextKit无法构建出一个完全匹配的内容, 在某些情况下总会存在误差.

比如 富文本中 存在中英文不同字体混合的情况, 最终显示会不一致.

目前进展:

UILabel 真实的NSAttributedString对象的获取已解决, 可以肯定的是目前得到的NSAttributedString对象是准确无误的. 无需再考虑这方面的问题.

通过各种实践已知 TextKitUILabel的行高计算策略不同, 导致相同的NSAttributedString对象实际渲染后显示的不一样.

已经尝试使用Neat的方案解决, Neat本身存在很多问题, 比如富文本中包含NSTextAttachment Neat 就会出现问题, 幸运的是 这个问题我已经解决了. 其他问题目前还没有解决, 比如 numberOfLines会导致计算出错. Neat的方案是否真正可靠还是个未知数, 但最起码它是目前最接近成功的一种方案, 你可以考虑继续使用Neat的方案走下去, 也可以另辟蹊径.

如何进行测试:

目前该分支内已经包含了调试代码. 在 CheckingViewController.swift文件中, 点击label后 会创建一个DebugView添加到UILabel上, DebugView上显示的内容由TextKit绘制, 如果所显示的内容完全重合 则表示通过, 如果出现不一致的情况 则表示不通过.

例子:

debug

通过:

success

不通过:

failure

分支地址

调试页面: image

相关类: image

lixiang1994 avatar Aug 03 '20 11:08 lixiang1994

先调用layoutIfNeeded,之后在用sizeThatFits计算高度

CoderLocus avatar Aug 03 '20 12:08 CoderLocus

先调用layoutIfNeeded,之后在用sizeThatFits计算高度

??? 要不先仔细看看问题?

lixiang1994 avatar Aug 03 '20 12:08 lixiang1994

当前状态: 实践中, 感谢MPITextKit作者wanhmr提供的帮助.

lixiang1994 avatar Aug 04 '20 03:08 lixiang1994

大部分情况已经得到了解决, 目前已知的问题还剩下一个:

label.numberOfLines=2 
lable.text = "abc\n\n\ndefg"

TextKit的截断处理有问题, 即使字符串中包含了3个换行, TextKit依旧会将"edfg"显示在第二行.

lixiang1994 avatar Aug 06 '20 12:08 lixiang1994

已知问题增加: Label的lineBreakMode属性为byCharWrapping时 无法对齐, 同时当numberOfLines非0时, TextKit甚至会出现显示错乱.

lixiang1994 avatar Aug 14 '20 05:08 lixiang1994

重新打开 此征集依旧有效

为方便测试 我专门构建了一个UILabel的Debug页面, 运行Demo工程.

支持保持当前配置, 下一次打开时自动恢复保存的配置, 通过点击右上角 Save 按钮进行, 配置数据将以Json格式存储到UserDefaults中, 如果你需要导出配置 可以在保存后通过UserDefaults获取.

image image

lixiang1994 avatar Aug 14 '20 10:08 lixiang1994

目前主要问题集中在发生文本截断时(numberOfLines非0 或 高度低于内容高度时)和段落样式的某些情况时, 我不清楚UILabel内部是如何处理截断的, 希望有了解的同道们能够指点一下, 万分感谢🙏.

lixiang1994 avatar Aug 14 '20 10:08 lixiang1994

有尝试过发起Developer Technical Support么,感觉这种黑盒问题可以直接问官方

hstdt avatar Jan 17 '22 08:01 hstdt

有尝试过发起Developer Technical Support么,感觉这种黑盒问题可以直接问官方

还没有, 感觉上来看 只能通过用自己创建的视图绘制来避免这种问题.

lixiang1994 avatar Jan 17 '22 09:01 lixiang1994

感觉文本截断问题是不是可以通过重写drawGlyphs(forGlyphRange:at:)来做到模拟UILabel的行为。

douknow avatar Apr 22 '22 10:04 douknow