我有一个符合布尔值的ObservableObject的Day。 在白天,一共有3个班次。
在这3个数组中,只要有一个用户等于当前用户,我就会尝试更新视图。
当前尝试使用Combine,并且在显示视图时似乎可以使用,但是从所有shift.employees
数组中删除当前用户后,它仍然为真。
我要观察的布尔值是hasShifts。如果为true,则应该是一个小圆圈指示器;如果为false,则应该为空。
我不知道我的错误在哪里,所以我在这里发布了与此问题相关的所有代码。另外,如果您有更好,更合适的方法来达到此效果,请告诉我。
Demo picture, deleted the user from every shift and the orange circle still exists.
主视图:
struct SetWeekdaysShiftsView: View {
@EnvironmentObject var session: SessionStore
var body: some View {
ScrollView{
WeekRow()
ForEach(session.week){ day in
ShiftTypesView(day: day)
}
}
}
包含班次的组框:
struct ShiftTypesView: View{
@ObservedObject var day: Day
@State private var showAll = false
@State private var buttonText = "Expand"
var body: some View{
if day.isSelected{
GroupBox(label: HStack{
Text(day.date ?? "")
Spacer()
Button {
withAnimation(.spring()){
self.showAll.toggle()
if self.showAll{
buttonText = "Collapse"
}else{
buttonText = "Expand"
}
for shift in day.shifts{
shift.isSelected.toggle()
}
}
} label: {
Text(LocalizedStringKey(buttonText))
.font(.subheadline)
}
}) {
Divider()
withAnimation(.spring()){
ForEach(day.shifts){ shift in
ShiftRow(shift: shift, show: $showAll)
.padding(8)
.background(Color(UIColor.systemGray6))
.cornerRadius(10)
}
}
}
.padding(.horizontal)
.padding(.bottom)
.groupBoxStyle(RoundedGroupBoxStyle(paddingTop: false))
}
}
}
从同一班次的employees数组中删除所需的用户。
fileprivate struct ShiftRow: View{
@ObservedObject var shift: Shift
@Binding var show: Bool
var body: some View{
DisclosureGroup(LocalizedStringKey(shift.type!.description()), isExpanded: $shift.isSelected ) {
ForEach(shift.employees){ employee in
EmployeeRow(employee: employee)
.onTapGesture {
withAnimation(.spring()){
if !self.shift.removedEmployees.contains(where: {$0.employeeId == employee.employeeId}){
removeEmployee(employee: employee)
}
}
}
}
HStack{
Menu {
if shift.removedEmployees.count != 0{
ForEach(shift.removedEmployees){emp in
Button(emp.name){
withAnimation(.spring()){
self.shift.employees.append(emp)
self.shift.removedEmployees.removeAll(where: {$0.id == emp.id})
}
}
}
}
} label: {
if self.shift.removedEmployees.count != 0{
Label(LocalizedStringKey("Add Employee"), systemImage: "plus.circle.fill")
}else{
Label(LocalizedStringKey("Add Employee"), systemImage: "plus.circle.fill")
.foregroundColor(Color.blue.opacity(0.3))
}
}
Spacer()
}.padding(8)
}
}
private func removeEmployee(employee: Employee){
withAnimation(.spring()){
if let index = self.shift.employees.lastIndex(where: {$0.id == employee.id}){
print("Removed \(employee.name)")
self.shift.employees.remove(at: index)
self.shift.removedEmployees.append(employee)
}
}
}
}
包含数据并发布以查看的日项目(工作日[其中有hasShift布尔值]):
struct WeekItem: View {
@StateObject var day: Day
var body: some View {
VStack{
VStack(spacing: 8){
Text(day.daySymbol)
.foregroundColor(.secondary)
.font(.callout)
ZStack{
Circle()
.fill(day.isSelected ? Color.blue : Color.clear)
.frame(width: 30, height: 30, alignment: .center)
.scaleEffect(day.isSelected ? 1.2 : 1)
.animation(.spring(response: 0.3, dampingFraction: 0.6, blendDuration: 0))
Text(day.dayNumber)
.foregroundColor(day.isSelected ? Color.white : Color.secondary)
.font(.system(size: 15, weight: .bold, design: .rounded))
}
}
Circle()
.fill(day.isSelected ? Color.orange : Color.blue)
.frame(width: 5, height: 5, alignment: .center)
//THIS IS THE BOOLEAN
.opacity(day.hasShifts ? 1 : 0)
.scaleEffect(day.isSelected ? 1.2 : 1)
.animation(.spring(response: 0.3, dampingFraction: 0.6, blendDuration: 0))
}
}
}
一天的observableObject:
class Day: Codable, Identifiable, Hashable, ObservableObject{
private var session = SessionStore.shared
var id = UUID()
@Published var shifts = [Shift].init(repeating: Shift(), count: 3)
@Published var date: String?
@Published var isSelected = false
@Published var hasShifts = false
@Published var daySymbol = ""
@Published var dayNumber = ""
var isApplied = false
var timeStamp = Date().timeInterval
private var cancellables = Set<AnyCancellable>()
init(){
}
init(date: String, isSelected: Bool, hasShifts: Bool, daySymbol: String, dayNumber: String){
self.date = date
self.isSelected = isSelected
self.hasShifts = hasShifts
self.daySymbol = daySymbol
self.dayNumber = dayNumber
}
func setShifts(morning: [Employee], middle: [Employee], evening: [Employee]){
let morning = Shift(type: .Morning, employees: morning)
let middle = Shift(type: .Middle, employees: middle)
let evening = Shift(type: .Evening, employees: evening)
self.shifts[0] = morning
self.shifts[1] = middle
self.shifts[2] = evening
isApplied = true
self.$shifts
.map{ shifts in
return shifts.contains(where: {$0.employees.contains(where: {$0.name == self.session.user?.name})})
}
.sink{ input in
self.hasShifts = input
}
.store(in: &cancellables)
}
从服务器以阵列形式接收所有员工后,在SessionStore中使用此功能实施7天阵列。 (列表)
for (i, d) in date.weekDaySymbols.enumerated(){
let day = Day(date: date.nextWeek[i], isSelected: false, hasShifts: false, daySymbol: d.uppercased(), dayNumber: date.nextWeekNumbers[i])
day.setShifts(morning: list, middle: list, evening: list)
if i == 0 {day.isSelected = true}
self.week.append(day)
}