警报视图使父视图使用SwiftUI重新初始化

时间:2020-09-20 19:08:35

标签: ios swift swiftui

我的问题是,当我显示警报时,视图似乎会自行重新创建它并使显示的偏移相等。

我可能由于缺乏知识而错过了一些东西,但找不到这种行为的任何解释。

有人可以为我解释发生了什么事吗?

Problem Demo - the same happen if I change the date or the notes field

我的代码:


    class ShiftConstModel: Identifiable, ObservableObject{

    @Published var shifts = [ShiftConst]()
    @Published var isFinished = false
    
    private var session = SessionStore.shared
    
    init(count: Int){
        
        let shift = ShiftConst(date: Date().timeInterval, shiftType: .Morning, notes: nil, applyTime: Date(), employeeId: 0, uid: "session.user!.uid")
        
        self.shifts = [ShiftConst].init(repeating: shift, count: count)
    }
    
    init(){
        fetchData()
    }
    
    func fetchData(){
        let ref = session.db.collection(CollectionRef.users.rawValue).document(session.user!.uid).collection("shiftConsts").order(by: "applyTime", descending: true)
        
        ref.addSnapshotListener { (qSnapshot, error) in
            
            guard let qSnapshot = qSnapshot, !qSnapshot.isEmpty else {
                print("Snapshot ERROR: ", error ?? "No errors")
                return
            }
            
            self.shifts = qSnapshot.documents.compactMap { (snapshot) -> ShiftConst? in
                return try? snapshot.decode(as: ShiftConst.self)
            }
        }
    }
    
    func setShifts(completion: @escaping (Bool) -> () = {_ in}){
        let group = DispatchGroup()
        
        for shift in shifts{
            group.enter()
            let ref = session.db.collection(CollectionRef.users.rawValue).document(shift.date.toFormat(DateFormats.format11.rawValue))
            
            do{
                let data = try shift.toJson()
                session.db.batch().setData(data, forDocument: ref).commit()
                isFinished = true
            }catch let error{
                isFinished = false
                print(error)
            }
            group.leave()
        }
        
        group.notify(queue: .main){
            if self.isFinished{
                completion(true)
            }else{
                completion(false)
            }
        }
    }
}

class ShiftConst: Codable, Identifiable, Hashable, ObservableObject{
    
    static func == (lhs: ShiftConst, rhs: ShiftConst) -> Bool {
        return lhs.shiftType == rhs.shiftType && lhs.id == rhs.id && lhs.date == rhs.date
    }
    
    func hash(into hasher: inout Hasher) {
        hasher.combine(shiftType)
        hasher.combine(date)
        hasher.combine(available)
        hasher.combine(notes)
        hasher.combine(applyTime)
        hasher.combine(employeeId)
        hasher.combine(uid)
    }
    
    var id = UUID()
    var date: Date
    var shiftType: ShiftType
    var available = true
    var notes: String
    var applyTime: Date
    var employeeId: Int
    var uid: String
    
    enum CodingKeys: String, CodingKey {
        case date
        case shiftType
        case available
        case notes
        case applyTime
        case employeeId
        case uid
    }

    init(date: Date, shiftType: ShiftType, notes: String?, applyTime: Date, employeeId: Int, uid: String){
        self.date = date
        self.shiftType = shiftType
        self.employeeId = employeeId
        self.uid = uid
        self.applyTime = applyTime.timeInterval
        
        if let notes = notes{
            self.notes = notes
        }else{
            self.notes = ""
        }
    }
    
    required init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        date = try container.decode(Date.self, forKey: .date)
        shiftType = try container.decode(ShiftType.self, forKey: .shiftType)
        available = try container.decode(Bool.self, forKey: .available)
        notes = try container.decode(String.self, forKey: .notes)
        applyTime = try container.decode(Date.self, forKey: .applyTime)
        employeeId = try container.decode(Int.self, forKey: .employeeId)
        uid = try container.decode(String.self, forKey: .uid)
    }
    
    func encode(to encoder: Encoder) throws {
        var container = encoder.container(keyedBy: CodingKeys.self)
        try container.encode(date, forKey: .date)
        try container.encode(date, forKey: .shiftType)
        try container.encode(date, forKey: .available)
        try container.encode(date, forKey: .notes)
        try container.encode(date, forKey: .applyTime)
        try container.encode(date, forKey: .employeeId)
        try container.encode(date, forKey: .uid)
    }
}

视图:


    struct ShiftConstCell: View{
    
    @ObservedObject var shift: ShiftConst
    
    var body: some View{
        DatePicker(LocalizedStringKey("Choose day:"), selection: $shift.date, in: Date().closedRange, displayedComponents: .date)
        ShiftSegmentControl(selectedShift: $shift.shiftType)
        HStack{
            Text("Notes:")
            TextField("Optional", text: $shift.notes)
        }
    }
}

struct SetShiftsView: View {
    
    @Environment(\.presentationMode) var presentationMode
    @Environment(\.timeZone) var timeZone
    @EnvironmentObject var session: SessionStore
    
    @State private var showAlert = false
    @State private var showLoader = false
    @State private var alertItem: AlertItem?
        
    @ObservedObject var viewModel = ShiftConstModel(count: 2)
    
    var body: some View{
        NavigationView{
            Form{
                ForEach(viewModel.shifts){ shift in
                    Section{
                        ShiftConstCell(shift: shift)
                    }
                }
            }
            .navigationBarTitle(Text("Send Shifts"), displayMode: .inline)
            .toolbar(content: {
                ToolbarItem(placement: .navigationBarLeading){
                    Button("Back"){
                        self.presentationMode.wrappedValue.dismiss()
                    }
                }
                ToolbarItem(placement: .navigationBarTrailing){
                    Button("Send"){
                        self.showAlert.toggle()
                    }
                }
                ToolbarItem(placement: .principal){
                    if self.showLoader{
                        ProgressView()
                    }
                }
            })
            .alert(isPresented: $showAlert) { () -> Alert in
                Alert(title: Text("Test"))
            }
        }
        
        
    }
    
}

0 个答案:

没有答案