首页 > 解决方案 > 无论选择什么行,SwiftUI 列表视图都会打开相同的 PDF - 也无法删除列表的扩展名

问题描述

我列出了存储在包中的 PDF 数组。但是,无论我选择哪一行,它总是显示列表中的第一项。我不明白为什么会发生这种情况,因为我在pdf[item]呈现工作表时正在使用它。

我遇到的另一个问题是我似乎无法删除所列文档的扩展名。我已经尝试添加dropLast(4)let = pdf但它似乎没有做任何事情。

注意:(bundleLoc根据其他选择而变化,但为了解释,我已将其更改为"/Products/PDF"

这是我列出所有 PDF 的地方:

struct ProductTab5View: View {
    
    @State var showingDetail = false
    
    var body: some View {
        ScrollView(.vertical){
            VStack(alignment: .leading){
                let bundleLoc = "/Products/PDF"
                let pdf = Bundle.main.urls(forResourcesWithExtension: "pdf", subdirectory: bundleLoc)?
                    .compactMap { $0.lastPathComponent } ?? []
                    .dropLast(4)

                ForEach(0..<pdf.count, id: \.self) { item in
                    Button(action: {
                        self.showingDetail.toggle()
                    }, label: {
                        Text(pdf[item])
                    })
                    .sheet(isPresented: $showingDetail) {
                        PDFKitView(pdfName: pdf[item], pdfLocation: bundleLoc)
                    }
                }
            }
        }
    }
}

这是 PDFViewer 结构的一部分:

struct PDFKitView: View {
    
    var pdfName: String
    var pdfLocation: String
    
    var body: some View {
        PDFViewer(url: Bundle.main.url(forResource: self.pdfName, withExtension: nil, subdirectory: pdfLocation)!)
            .ignoresSafeArea(edges:.bottom)
    }
}

标签: iosswiftswiftui

解决方案


你这里有几个问题。

首先,要删除.pdf您需要在 上使用的扩展名dropLast(4)String而不是ArraycompactMap.

其次,您实际上是在为循环.sheet的每次迭代创建一个ForEach。所有工作表的可见性都由 控制$showingDetail,但您只能看到最顶层(第一个)工作表。

我会建议一些改进:

  1. 存储一个数组URL而不是String- 这样您就不需要URLPDFKitView.
  2. 使用@Statevar 指示URL应该显示哪个
  3. 直接遍历数组。没有必要使用index
struct ProductTab5View: View {
    
    @State var showingDetail = false
    @State var pdfURL: URL?
    
    var body: some View {
        ScrollView(.vertical){
            VStack(alignment: .leading){
                let bundleLoc = "/Products/PDF"
                let pdfs = Bundle.main.urls(forResourcesWithExtension: "pdf", subdirectory: bundleLoc) ?? []
                ForEach(pdfs, id: \.self) { pdf in
                    Button(action: {
                        self.pdfURL = pdf
                        self.showingDetail.toggle()
                    }, label: {
                        Text((pdf.lastPathComponent ?? "").dropLast(4))
                    })
                }
                .sheet(isPresented: $showingDetail) {
                        PDFKitView(pdf: self.$pdfURL)
                }
            }
        }
    }
}
    
struct PDFKitView: View {
    @Binding var pdf: URL?
    var body: some View {
        if let url = self.pdf { 
            PDFViewer(url: url)
                .ignoresSafeArea(edges:.bottom)
        } else {
            Text("PDF Not found")
        }
        
    }
}


推荐阅读