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

moo*_*der 5 ios swift swiftui swiftui-navigationlink

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

点击按钮后,该 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()
    }
}
Run Code Online (Sandbox Code Playgroud)

Raj*_*han 0

可能的解决方案

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)
        }
    }
}
Run Code Online (Sandbox Code Playgroud)