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

SwiftUI展示QLPreviewController时无法滑动关闭的问题求助

SwiftUI中QLPreviewController滑动关闭失效及导航栏缺失问题

在SwiftUI应用中使用QLPreviewController展示图片时,发现两个与UIKit模态展示不一致的问题:

  1. UIKit中模态展示QLPreviewController时,会自动将其包裹在UINavigationController中,且支持下滑图片直接关闭控制器;
  2. SwiftUI中通过.fullScreenCover展示时,既没有自动添加的UINavigationController,下滑关闭的交互也完全失效。

UIKit示例代码

import UIKit
import QuickLook

class ViewController: UIViewController {
    let button = UIButton(type: .system)
    
    let url = Bundle.main.url(forResource: "foo", withExtension: "jpg")!

    override func viewDidLoad() {
        super.viewDidLoad()
        
        button.setTitle("Preview", for: .normal)
        self.view.addSubview(button)
        button.addTarget(self, action: #selector(buttonTapped(_:)), for: .touchUpInside)
    }
    
    override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()
        button.frame = CGRect(x: (view.frame.size.width - 150)/2, y: (view.frame.size.height - 44)/2, width: 150, height: 44)
    }

    @IBAction func buttonTapped(_ button: UIButton) {
        let previewController = QLPreviewController()
        previewController.dataSource = self
        present(previewController, animated: true)
    }
}

extension ViewController : QLPreviewControllerDataSource {

    @objc func numberOfPreviewItems(in controller: QLPreviewController) -> Int {
        return 1
    }

    func previewController(_ controller: QLPreviewController, previewItemAt index: Int) -> QLPreviewItem {
        return url as QLPreviewItem
    }
}

SwiftUI示例代码

import Foundation
import SwiftUI
import QuickLook

struct ContentViewSimple: View {
    
    @StateObject private var previewURL = URLContainer()
    
    var body: some View {
        VStack {
            Button("Preview", action: {
                previewURL.url = Bundle.main.url(forResource: "foo", withExtension: "jpg")
            })
        }
        .fullScreenCover(item: $previewURL.url, content: { url in
            QuickLookPreviewSimple(url: url)
        })
    }
}

class URLContainer : ObservableObject {
    @Published var url : URL?
}

struct QuickLookPreviewSimple: UIViewControllerRepresentable {
        
    let url: URL
    
    func makeUIViewController(context: Context) -> QLPreviewController {
        let controller = QLPreviewController()
        controller.dataSource = context.coordinator
        return controller
    }
    
    func updateUIViewController(_ uiViewController: QLPreviewController, context: Context) {
    }
    
    func makeCoordinator() -> Coordinator {
        return Coordinator(parent: self)
    }
    
    class Coordinator : NSObject, QLPreviewControllerDataSource {
        let parent: QuickLookPreviewSimple
        
        init(parent: QuickLookPreviewSimple) {
            self.parent = parent
        }
        
        @objc func numberOfPreviewItems(in controller: QLPreviewController) -> Int {
            return 1
        }
        
        func previewController(_ controller: QLPreviewController, previewItemAt index: Int) -> QLPreviewItem {
            return parent.url as QLPreviewItem
        }
    }
}

已尝试的解决方法

  • 手动将QLPreviewController包裹在UINavigationController中:可添加工具栏和Done按钮关闭,但滑动关闭仍无效;
  • 使用.sheet替代.fullScreenCover:仅能通过滑动导航栏/工具栏关闭,下滑图片的交互仍无作用;
  • 使用.quickLookPreview替代.fullScreenCover:自动添加UINavigationBar,但滑动关闭功能依然不生效。

请问这是SwiftUI的遗留问题需要Apple修复,还是存在可行的解决办法?


内容的提问来源于stack exchange,提问作者Greg G

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 17:10:38