You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SwiftUI中PDFView获取当前页码及绑定UI更新异常问题

问题:PDFKit滑动翻页时无法同步更新SwiftUI中的当前页码显示

我正在使用PDFKit开发PDF阅读器应用,已通过pdfView.usePageViewController(true)启用原生滑动翻页功能,但无法获取并同步当前页码到SwiftUI界面。目前可以通过pdfView.document?.pageCount获取总页数,也能通过按钮翻页手动计数,但希望保留原生滑动体验。

按照建议添加Coordinator类后,控制台能打印正确的页码变化,但通过Binding将currentPage传递给SwiftUI时,界面上的页码不更新,同时滑动翻页仅会重复显示前两页。


初始代码

ContentView

struct ContentView: View {
    let url = Bundle.main.url(forResource: "file", withExtension: "pdf")
    var body: some View {
        VStack{
            PDFKitRepresentedView(data: try! Data(contentsOf: url!))
        }
    }
}
struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

PDFKitRepresentedView

import PDFKit
import SwiftUI

struct PDFKitRepresentedView: UIViewRepresentable {
    typealias UIViewType = PDFView
    let data: Data
    func makeUIView(context _: UIViewRepresentableContext<PDFKitRepresentedView>) -> UIViewType {
        // Create a `PDFView` and set its `PDFDocument`.
        let pdfView = PDFView(frame: CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height))
        pdfView.document = PDFDocument(data: data)
        pdfView.backgroundColor = UIColor.red
        pdfView.displayMode = .singlePage
        pdfView.displayDirection = .horizontal
        pdfView.usePageViewController(true)
        pdfView.maxScaleFactor = pdfView.scaleFactorForSizeToFit
        pdfView.minScaleFactor = pdfView.scaleFactorForSizeToFit
        pdfView.autoScales = true
        
        return pdfView
    }
    func updateUIView(_ pdfView: UIViewType, context _: UIViewRepresentableContext<PDFKitRepresentedView>) {
        pdfView.document = PDFDocument(data: data)
    }
}

更新后的代码

ContentView

struct ContentView: View {
    @State var currentPage = -1
    @State var totalPages :Int?
    let url = Bundle.main.url(forResource: "file", withExtension: "pdf")
    var body: some View {
        VStack{
            HStack{
                Text("\(currentPage)/")
                Text("\(totalPages ?? 0)")
            }
            if let url = url {
                PDFKitRepresentedView(data:try! Data(contentsOf: url),totalPages: $totalPages,currentPage: $currentPage)
            }
        }
    }
}

PDFKitRepresentedView

struct PDFKitRepresentedView: UIViewRepresentable {
    typealias UIViewType = PDFView
    let data: Data
    @Binding var totalPages:Int?
    @Binding var currentPage :Int
    let pdfView = PDFView(frame: CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height))

    func makeUIView(context: Context) -> UIViewType {
        pdfView.document = PDFDocument(data: data)
        pdfView.backgroundColor = UIColor.red
        pdfView.displayMode = .singlePage
        pdfView.displayDirection = .horizontal
        pdfView.usePageViewController(true)
        pdfView.maxScaleFactor = pdfView.scaleFactorForSizeToFit
        pdfView.minScaleFactor = pdfView.scaleFactorForSizeToFit
        pdfView.autoScales = true
        pdfView.delegate = context.coordinator
        return pdfView
    }
    
    func updateUIView(_ pdfView: UIViewType, context _: Context) {
        pdfView.document = PDFDocument(data: data)
        DispatchQueue.main.async {
            totalPages = pdfView.document?.pageCount
        }
    }
    
    func makeCoordinator() -> Coordinator {
        return Coordinator(self, cp: $currentPage)
    }
        
    class Coordinator: NSObject, PDFViewDelegate {
        var parent: PDFKitRepresentedView
        @Binding var currentPage :Int
        
        init(_ parent: PDFKitRepresentedView,cp:Binding<Int>) {
            self.parent = parent
            _currentPage = cp
            super.init()
            NotificationCenter.default.addObserver(self, selector: #selector(pageChangeHandler(_:)), name: .PDFViewPageChanged, object: nil)
        }

        @objc func pageChangeHandler(_ notification: Notification) {
            
            if let thePage = parent.pdfView.currentPage,
                let ndx = parent.pdfView.document?.index(for: thePage),
               currentPage != ndx {
                DispatchQueue.main.async {
                    self.currentPage = ndx
                }
                print("--------> currentPageIndex: \(ndx) ")
            }
        }
    }
}

内容的提问来源于stack exchange,提问作者Iftikhar Hussain

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 22:50:24