在我的应用中,我希望用户可以选择将接收到的数据(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发生后立即更新列表