如何从列表中删除数据并更新视图

时间:2020-05-15 11:02:38

标签: swift xcode list swiftui combine

在我的应用中,我希望用户可以选择将接收到的数据(GenAirportModel)划分到个人文件夹中。

我已经创建了文件夹模型:

import Foundation
import Combine
class FolderModel : Identifiable , Codable{

    var nameFolder : String
    var vectorData : [GenAirportModel]

    init(nameFolder: String, vectorData: [GenAirportModel]) {
        self.nameFolder = nameFolder
        self.vectorData = vectorData
    }
}

我有我的文件夹管理器

import UIKit
import Combine
import SwiftUI

class FolderManager: ObservableObject {
    let objectWillChange = PassthroughSubject<Void,Never>()

    let basicAirport = GenAirportModel(airportData: AirportModel(aptICAO: "TestICAO", aptName: "", aptCity: "", aptCountry: "", aptIATA: ""), metarData: MetarModel(raw_text: "", observation_time: "", temp_c: 0.0, dewpoint_c: 0.0, wind_dir_degrees: 0, wind_speed_kt: 0, visibility_statute_mi: 0.0, altim_in_hg: 0.0, sea_level_pressure_mb: 0.0, sky_condition: "", flight_category: ""), tafData: TafModel(raw_text: "", issue_time: "", valid_time_from: "", valid_time_to: "", forecast: [TafModel.forecastModel(forcast_time_from: "", forcast_time_to: "", change_indicator: "", time_becoming: "", probability: 0, wind_dir_degrees: 0, wind_speed_kt: 00, wing_gust_kt: 00, wind_shear_hgt_ft_agl: 00, wind_shear_dir_degrees: 00, wind_shear_speed_kt: 00, visibility_statute_mi: 100, altim_in_hg: 1013, vert_vis_ft: 000, wx_string: "", sky_condition: [TafModel.forecastModel.SkyCondition(skyconditionCover: "", skyconditionCloudBase: "", skyconditionCloudType: "")], turbulence_condition: "")]), runwayData: [RunwayModel(name1: RunwayModel.Runway(lengthM: "", lengthF: "", hasLighting: true, widthM: "", widthF: "", surface: "", isClosed: true, name: "", trueHdg: "", displacedThresholdM: "", displacedThresholdF: "", locationLat: 00.00, locationLong: 00.00), name2: RunwayModel.Runway(lengthM: "", lengthF: "", hasLighting: true, widthM: "", widthF: "", surface: "", isClosed: true, name: "", trueHdg: "", displacedThresholdM: "", displacedThresholdF: "", locationLat: 00.00, locationLong: 00.00))])

    static let shared = FolderManager()

    var folderVector : [FolderModel] = []{
        didSet {
            objectWillChange.send()
        }
    }

    typealias Storage = [FolderModel]

    var filePath : String = ""

    init() {
        self.caricaDati()
        debugPrint("caricato dati folder")
    }

    func caricaDati() {
        // creiamo il percorso al file
        filePath = cartellaDocuments() + "/FolderList.plist"

        // usiamo NSFileManager per sapere se esiste un file a quel percorso
        if FileManager.default.fileExists(atPath: filePath) {

            // se c'è de-archiviamo il file di testo nell'array
            // serve il blocco do try catch
            do {
                // proviamo a caricare il file dal percorso creato in precedenza
                let data = try Data(contentsOf: URL(fileURLWithPath: filePath))
                // creiamo il decoder
                let decoder = PropertyListDecoder()
                // proviamo a decodificare il file nell'array
                folderVector = try decoder.decode(Storage.self, from: data)
            } catch {
                // se non ce la fa scriviamo in console l'errore
                debugPrint(error.localizedDescription)
            }

            // adesso abbiamo i dati e possiamo far andare l'App

            // *** ATTENZIONE***
            // funziona solo se il Model è conforme a Codable
            // *** ********* ***
        } else {

            // during first load of the app create Airport Vector
            debugPrint("PRIMO AVVIO NO FOLDER DATA")

        }
    }

    func salva() {
        // creiamo l'encoder
        let encoder = PropertyListEncoder()
        encoder.outputFormat = .xml // impostiamo l'output corretto
        // serve il blocco do try catch
        do {
            // proviamo a codificare l'array
            let data = try encoder.encode(folderVector)
            // proviamo a salvare l'array codificato nel file
            try data.write(to: URL(fileURLWithPath: filePath))
        } catch {
            // se non ce la fa scriviamo in console l'errore
            debugPrint(error.localizedDescription)
        }

        // *** ATTENZIONE***
        // funziona solo se il Model è conforme a Codable
        // *** ********* ***
    }

    func newFolder(name: String) {

        let newFolder: FolderModel = FolderModel(nameFolder: name, vectorData: [])
        folderVector.append(newFolder)
        salva()
    }


    func addDataToFolder(data: GenAirportModel, folderName: String){

        let firstTro = folderVector.first { (firstVal) -> Bool in
            firstVal.nameFolder == folderName

        }

        firstTro?.vectorData.append(data)
        salva()
    }


    func cartellaDocuments() -> String {
        let paths = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)
        //print(paths[0])
        return paths[0]
    }
}

然后我的视图列出了该文件夹:

struct FolderView: View {
    @ObservedObject var fm : FolderManager
    @State var addFolder = false
    @ObservedObject var dm : DataManager
    var body: some View {
        VStack{
            if addFolder {
                ADDFolder(fm: self.fm, isDiplayed: $addFolder).animation(.easeInOut)
            }
            // list folder
            NavigationView{

                List {
                    // list all folder created
                    ForEach(self.fm.folderVector) { folder in

                        NavigationLink(destination:

                            VStack{
                                if folder.vectorData.isEmpty {
                                    Text("no data")
                                        .navigationBarTitle(Text("test List"), displayMode: .inline)
                                        .navigationBarHidden(true)
                                        .navigationBarBackButtonHidden(true)


                                } else {

                                    FolderViewAirport(fm: self.fm, dm: self.dm, folders: folder)

                                }

                            }

                        ) {
                            HStack{
                                Image(systemName: "folder")
                                Text(folder.nameFolder)
                            }
                        }

                    }
                .onDelete(perform: delete)
                .onMove(perform: move)
                }


                .navigationBarTitle(Text("Folder List"), displayMode: .inline)
                .navigationBarItems(leading: Button(action: {
                    self.addFolder.toggle()
                }, label: {
                    Image(systemName: "plus")
                }), trailing: EditButton()

            )
                // nel prima schermata

            }.animation(.easeInOut)
        }
    }

       func move(from source : IndexSet, to destination: Int){
         fm.folderVector.move(fromOffsets: source, toOffset: destination)
         fm.salva()
     }
     func delete(at offset: IndexSet) {
         fm.folderVector.remove(atOffsets: offset)
         fm.salva()
     }
}

在每个文件夹中查看:

struct FolderViewAirport: View {
    @ObservedObject var fm : FolderManager
    @ObservedObject var dm : DataManager
    var folders : FolderModel

    @State var isSheetPresented : Bool = false
    var body: some View {
        List{
            ForEach(folders.vectorData) { airport in
                Button(action: {
                    self.isSheetPresented.toggle()
                }) {
                    CellViewMain(dm: self.dm, lm: self.fm, general: airport)
                }

                .sheet(isPresented: self.$isSheetPresented) {
                    DetailsFolder(dm: self.dm, general: airport, dismissFlag: self.$isSheetPresented)
                }
            }
            .onDelete(perform: delete)
            .onMove(perform: move)
        }
        .navigationBarTitle(self.folders.nameFolder)
        .navigationBarItems(trailing: EditButton())
    }

    func move(from source : IndexSet, to destination: Int){
        folders.vectorData.move(fromOffsets: source, toOffset: destination)
           fm.salva()
       }
       func delete(at offset: IndexSet) {
        folders.vectorData.remove(atOffsets: offset)
           fm.salva()
       }
}

我的问题是,当我尝试滑动从FolderViewAirport删除数据时,视图不会立即更新,我必须返回导航视图并返回FolderViewAirport来查看更改。

但是,如果我删除整个文件夹,则在文件夹视图中,我会看到更改立即出现。

我怀疑是因为在FolderManager上观察到folderVector带有objectwillchange,所以更改立即发布到视图,但未观察到文件夹vector内的vectorData。如何观察vectorData中的每一个变化?

非常感谢

在下面的图片中,我们位于单个文件夹内,其中delate函数不会在delate发生后立即更新列表

inside folder, here delate not work

0 个答案:

没有答案