PDFKit中PDFViewPageChanged通知不可靠,检测PDF末页误触发如何解决
问题原因
你遇到的异常触发问题主要来自以下几个原因:
- 通知监听范围过宽:你调用
addObserver时object参数传入了nil,这意味着你会接收到当前App中所有PDFView实例发出的PDFViewPageChanged通知。由于你的页面承载了多份PDF文档,其他PDF视图的翻页动作也会触发你的回调逻辑,此时拿到的页码不属于你当前正在监听的documentId对应的文档,就会出现误判。 - 加载阶段自动触发通知:
PDFView在完成文档加载、首次渲染页面的时候,即使没有用户手动操作,也会主动发出PDFViewPageChanged通知,这就是你没有操作也能收到回调的原因。 - 文档未完全加载时取值不准确:在PDF文档还没完成全量加载的阶段,调用
pageCount、pageNumber有可能拿到临时的错误值,比如加载过程中内核临时返回当前页等于总页数的错误结果,等加载完成后又修正为正确的1/2,就会出现你日志里先输出2/2又跳回1/2的情况。
修复方案
- 缩小通知监听范围:注册通知时
object参数传入你要监听的对应PDFView实例,避免接收其他PDF视图的通知干扰。 - 增加匹配校验:回调中先校验触发通知的
PDFView是否和你当前documentId关联的PDF视图一致,匹配通过再进行页码判断。 - 增加加载完成判断:只有确认文档已经完全加载完成后,再执行末页判断逻辑,也可以加简单的防抖逻辑,连续两次回调都返回相同的末页结果再触发后续逻辑,避免临时错误值的影响。
优化后的代码参考
// 假设当前要监听的pdfView是你绑定documentId的目标视图 let targetPdfView: PDFView = ... documentId = ... obs = NotificationCenter.default.addObserver(forName: .PDFViewPageChanged, object: targetPdfView, queue: nil) { (notification) in guard let notificationPdfView = notification.object as? PDFView, // 确认触发通知的就是目标视图 notificationPdfView == targetPdfView, // 确认文档已经加载完成,pageCount为有效值 let totalPageNumber = notificationPdfView.document?.pageCount, totalPageNumber > 0, let currentPage = notificationPdfView.currentPage?.pageRef?.pageNumber, let _ = notificationPdfView.document?.string else { return } print("FB: notification: \(documentId) currentPage: \(currentPage)/\(totalPageNumber)" ) // 可额外加防抖逻辑,比如间隔300ms再判断一次页码是否还是末页,再执行后续业务逻辑 }
内容的提问来源于stack exchange,提问作者onthemoon
相关产品推荐
相关产品推荐

