宿主的点读书场景需要在 PDF 页面上叠加可点击热区(音频/视频/网页等),并支持 试读限制与阅读进度、书签的本地保存,这些能力此前 RDPDFReaderView 均不提供, 只能由宿主在阅读器之外自行叠加视图,无法跟随 SDK 的缩放、翻页和主题渲染同步。 新增 RDPDFReaderPageInteraction 描述热区(位置、图标、边框/填充样式、点击态、 闪烁与播放边框规则、内嵌视频),由新增的 RDPDFInteractionHotspotView 负责绘制, SVG 图标经 RDPDFReaderSVGIconLoader(基于 SDWebImage/SDWebImageSVGCoder)异步 解码后回填,避免阻塞主线程;点击事件通过 interactionHandler 回传给宿主,媒体 播放、路由等业务仍留在宿主侧。底部工具栏新增点读提示与连播按钮,状态由宿主驱动。 试读墙对齐 EPUB 侧 RDEPUBReaderTrialPolicy 的设计:以页为限制单位,可读页数在 配置了 trialPolicy 且宿主经 delegate 提供墙视图时生效,原始总页数、缩略图、目录 换算不受影响,只有传给 RDPDFReaderView 的有效页数会追加一页试读墙;翻页、目录 跳转、大纲的上界都统一收敛到可读范围,避免用户绕过热区跳转或朗读高亮跳进未授权页。 阅读进度与书签复用 RDPDFReaderPersistenceStore 已有的标注状态目录,新增 reader-state.json 承载,不需要宿主额外提供数据库表;RDPDFReaderPersistenceStore 同时实现 RDPDFReaderPersistence 协议对接这部分读写。
3.3 KiB
RDPDFReaderView
独立的 UIKit PDF 阅读交互 SDK。当前第一阶段只包含与业务无关的部分:分页、双指缩放、双击缩放、放大后拖动,以及画笔模式下的手势隔离。
主工程的下载、解密、缓存、链接、标注和持久化仍由现有 PDF Feature 管理;后续通过适配层逐步迁移,避免把业务问题和手势问题混在一起。
PDF 数据来源
普通 PDF 可以由 SDK 使用 PDFKit 直接解析:
let reader = try RDPDFReaderViewController(
pdfURL: fileURL,
bookIdentifier: stableBookID,
password: standardPDFPassword,
persistence: persistence,
annotationPersistence: annotationStore
)
自定义加密 PDF 继续由宿主解密并提供页面图片,不需要把原始文件交给 SDK:
let reader = RDPDFReaderViewController(
pageProvider: encryptedImageProvider,
persistence: persistence,
annotationPersistence: annotationStore
)
两种入口最终都转换为 RDPDFReaderPageProvider,共用翻页、缩放、目录、书签、OCR、标注和画笔功能。内置 PDFKit 数据源按需渲染页面、限制最大图片尺寸并使用内存缓存;能够读取的原生 PDF 文字会直接用于选择和标注,图片扫描页则按配置回退到 OCR。
调试入口
在任意测试宿主中 push RDPDFReaderDebugViewController():
navigationController?.pushViewController(RDPDFReaderDebugViewController(), animated: true)
验证顺序:
- 双指捏合能连续放大和缩小。
- 双击能在适配尺寸与两倍缩放之间切换。
- 放大后单指只能拖动内容,不能翻页。
- 切到“画笔模式”后,单指不再翻页,双指仍能缩放和拖动。
如果这个独立页面工作正常,而主阅读页仍失效,问题就能确定在主工程的页面层/覆盖层,而不是缩放内核。
图片型 PDF 的文本、复制与标注
主程序即使只能提供每页图片,也可以接入文字功能:
- 若主程序已有 PDF 解析结果,在
RDPDFReaderPageDescriptor.textRuns中传入文字和相对图片的0...1坐标;这条路径提供最准确的复制和高亮。 - 若没有文字坐标,使用
RDPDFReaderImageTextRecognizer对当前页图片按需 OCR,再把结果赋给RDPDFReaderImageTextLayerView.textRuns。 - OCR 也不可用时,文字层会提供区域框选;区域标注只显示“高亮、注释”,不会错误地提供复制。
高亮与注释统一使用 RDPDFReaderAnnotation,坐标同样是相对图片的 0...1 比例,缩放、旋转或重新渲染页面后仍能对齐。使用 RDPDFReaderPersistenceStore 保存时,请传入宿主稳定的书籍 ID(可附账号和内容版本)对应的目录,并对 addAnnotation、updateAnnotation、deleteAnnotation 的 throws 结果做错误提示;文件损坏或版本不兼容时 SDK 会拒绝覆盖原数据。
点读热区
宿主可在 RDPDFReaderPageDescriptor 中传入 interactions,SDK 负责绘制 SVG 图标、背景图与播放反馈;点击事件通过 RDPDFReaderViewController.interactionHandler 回传,媒体播放、网页或路由仍由宿主处理。页面资源异步补齐后,调用 reloadPageContent(at:) 刷新指定页;播放状态可通过 setActiveInteraction(identifier:) 更新。