我的问题是,当我显示警报时,视图似乎会自行重新创建它并使显示的偏移相等。
我可能由于缺乏知识而错过了一些东西,但找不到这种行为的任何解释。
有人可以为我解释发生了什么事吗?
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"))
}
}
}
}