使用 SwiftUI 从转换目的地返回时,我想将显示的列表更新为最新状态

Posted

技术标签:

【中文标题】使用 SwiftUI 从转换目的地返回时,我想将显示的列表更新为最新状态【英文标题】:I want to update the displayed list to the latest state when returning from the transition destination with SwiftUI 【发布时间】:2020-06-27 16:05:23 【问题描述】:

ListView 显示添加到收藏夹的项目列表。

转到 DetailView 并从您的收藏夹中删除该项目。

当我返回列表视图时,我想将其更新为最新列表。

你是怎么做到的?

代码

ListView.swift

显示 3x3 卡类型的列表。

struct ListView: View 
    @ObservedObject var fetcher = DataFetcher()
    private let columns: Int = 3

    var body: some View 
        GeometryReader  geometry in
            NavigationView 
                ScrollView() 
                    VStack 
                        ForEach(0..<self.fetcher.dataCount/self.columns)  rowIndex in
                            HStack 
                                ForEach(0..<self.columns)  columnIndex in
                                    self.getCell(
                                        item: self.getItem(rowIndex: rowIndex, columnIndex: columnIndex),
                                        width: self.cellWidth(width: geometry.size.width),
                                        height: self.cellHeight(width: geometry.size.width))
                                
                            
                        

                      if (self.fetcher.dataCount % self.columns > 0) 
                          HStack 
                              ForEach(0..<self.fetcher.dataCount % self.columns)  lastColumnIndex in
                                  self.getCell(
                                      item: self.getItem(lastColumnIndex: lastColumnIndex),
                                      width: self.cellWidth(width: geometry.size.width),
                                      height: self.cellHeight(width: geometry.size.width))
                              
                              Spacer()
                          
                      
                  
                  .frame(maxWidth: .infinity)
                
                .navigationBarTitle("list")
            
        
    

    private func cellWidth(width: CGFloat) -> CGFloat 
        return (width  - 60) / CGFloat(columns)
    

    private func cellHeight(width: CGFloat) -> CGFloat 
        return cellWidth(width: (width)) * 1.414
    

    private func getItem(rowIndex: Int, columnIndex: Int) -> TrackModel 
        return fetcher.data[columns * rowIndex + columnIndex]
    

    private func getItem(lastColumnIndex: Int) -> TrackModel 
        return self.fetcher.data[self.columns * (self.fetcher.dataCount / self.columns) + lastColumnIndex]
    

    private func getCell(item: ItemModel, width: CGFloat, height: CGFloat) -> AnyView 
        return AnyView(
            NavigationLink(
                destination: etailView(itemModel: item)
            ) 
                ItemRow(itemModel: item)
                .frame(width: width, height: height)
            
            .buttonStyle(PlainButtonStyle())
        )
    

DataFetcher.swift

Firestore 具有“用户”和“项目”的集合。

每个用户的文档都有一个“项目”的集合。

“items”有一个引用类型“item”,值为“items / documentID”。

class DataFetcher: ObservableObject 
    typealias PublisherType = PassthroughSubject
    @Published var data: [TrackModel] = []
    @Published var dataCount: Int = 0
    private let userDefaults = UserDefaults.standard
    private let uid: String
    private var db: Firestore!
    private let dispatchGroup = DispatchGroup()
    private let dispatchQueue = DispatchQueue(label: "queue")

    init() 
        db = Firestore.firestore()
        uid = self.userDefaults.object(forKey: "userDataUid") as! String
        fetchData()
    

    private func fetchData() 
        self.db.collection("users").document(uid).collection("items").getDocuments  (snaps, err) in
            if let err = err 
                print("Error getting documents: \(err)")
            

            guard let snaps = snaps else  return 

            for document in snaps.documents 
                self.dispatchGroup.enter()
                self.dispatchQueue.async(group: self.dispatchGroup)  [weak self] in
                    self?.asyncProcess(document: document)  (snap2: DocumentSnapshot) -> Void in
                        self!.data.append(TrackModel(
                            documentId: snap2.documentID,
                            title: snap2.data()!["title"] as! String,
                            image: snap2.data()!["image"] as! String
                        ))
                        self?.dispatchGroup.leave()
                    
                
            

            self.dispatchGroup.notify(queue: .main) 
                self.dataCount = self.data.count
            
        
    

    func asyncProcess(document: QueryDocumentSnapshot, completion: @escaping (_ snap: DocumentSnapshot) -> Void) 
        let refarence: DocumentReference = document.data()["item"] as! DocumentReference

        refarence.getDocument  (snap, err) in
            completion(snap!)
        
    

后记

当我使用 Modal 进入详细屏幕并返回列表屏幕时,我无法获取。

我该怎么办?

Button(action: 
    self.modalPresented.toggle()
) 
    Text("Go to Detail")


.sheet(isPresented: self.$modalPresented) 
    DetailView(onDismiss: 
        self.modalPresented = false
        self.fetcher.fetchData()
    )

【问题讨论】:

【参考方案1】:

如果你的意思是重新获取,这里有可能的方法

    让其他人可以使用您的提取功能
    class DataFetcher: ObservableObject 
        ...
        func fetchData()  // << here !
           ...

    当细节消失时启动重新获取

        NavigationLink(
            destination: DetailView(itemModel: item)
                             .onDisappear 
                                 self.fetcher.fetchData() // << here !
                             
        ) 
            ItemRow(itemModel: item)
            .frame(width: width, height: height)
        
    

【讨论】:

以上是关于使用 SwiftUI 从转换目的地返回时,我想将显示的列表更新为最新状态的主要内容,如果未能解决你的问题,请参考以下文章

Firebase+SwiftUI。无法转换价值

如何在 SwiftUI 中从一个详情页跳转到另一个详情页并返回列表页?

从 SwiftUI 视图返回文本

如何禁用“'NSInteger' 类型的值不应用作格式参数;改为将显式强制转换添加到 'long'”

带有使用数组字典的部分的 SwiftUI 列表

如何使用 SwiftUI 向 macOS 应用程序添加工具栏?