异步任务后在 SwiftUI 中的正确导航方式

Posted

技术标签:

【中文标题】异步任务后在 SwiftUI 中的正确导航方式【英文标题】:Proper way of Navigation in SwiftUI after async task 【发布时间】:2021-01-09 13:26:55 【问题描述】:

我有一个带有List 视图的屏幕,其中一个是NavigationLink,它导航到显示PDF 文档的单独屏幕DocumentPreviewView

此PDF文档需要在点击按钮后的第一个屏幕上异步下载,并需要传递到DocumentPreviewView屏幕。

我来到了工作解决方案,但我正在寻找更优雅的方式和更 SwiftUI 的方式。 也许文档应该是某种可观察的对象。

这是我目前的解决方案。如您所见,我使用了由按钮操作的回调触发的隐藏 NavigationLink,我还下载了需要展示的文档。

@State private var document = PDFDocument()
@State private var docState: DocState? = .setup

enum DocState: Int 
    case setup = 0
    case ready = 1


var body: some View 
    List 
    /// some other views

        Button(action: 
            someAsyncFunction  doc, error in 
              self.document = doc
              self.docState = .ready
            
          ) 
          Text("Show Document")
        

    /// some other views
    

    NavigationLink(
            destination: DocumentPreviewView(pdfDocument: document), 
            tag: .ready, 
            selection: $docState) 
        EmptyView()
    

【问题讨论】:

可能有几种方法,你使用其中一种,所以它是基于意见的。 @Asperi 对我来说这个解决方案中最奇怪的部分是我使用隐藏的 UI 组件,看起来更像是解决方法而不是优雅的解决方案 从用户体验的角度来看,我建议在用户与您的应用交互后立即导航到新屏幕,并在您下载 PDF 时显示微调器或加载栏。 @moonvader 不,它被广泛用于以编程方式激活导航的模式。只需在此处搜索 NavigationLink+EmptyView,您就会找到大量的用例。 【参考方案1】:

可能的解决方案

struct ContentView: View 
    @State private var docState: DocState? = .setup
    
    enum DocState: Int 
        case setup = 0
        case ready = 1
    
    
    
    var body: some View 
        NavigationView 
            ZStack 
                NavigationLink(
                    destination: Text("Preview"),
                    tag: .ready,
                    selection: $docState) 
                    Button(action: 
                        someTask()  isTaskDone in
                            docState = .ready
                        
                    ) 
                        Text("Download")
                    
                    
            
        
    
    
    func someTask(_ completion: @escaping ((Bool)->())) 
        DispatchQueue.main.asyncAfter(deadline: .now() + 1) 
            completion(true)
        
    

【讨论】:

这种情况下应该如何传递文件?我想我已经尝试过这种方法,但是传递文档时出现问题

以上是关于异步任务后在 SwiftUI 中的正确导航方式的主要内容,如果未能解决你的问题,请参考以下文章

Android:正确停止异步任务

异步下载图像时SwiftUI和Combine工作不顺畅

使用 WCF 中的任务构建异步操作合同的正确方法

swiftui 异步初始化

异步任务片段背景数据

导航抽屉异步任务