swift - DispatchQueue 使用 SwiftUI 触发 foreach 循环两次
问题描述
我的代码有一个奇怪的行为。
User
存在从对象获取其文本值的带有文本的视图。
如果我把引用拿出来,String
一切都很好,但是得到这个值的 foreach 循环会运行两次。
此外,如果我将分配从DispatchQueue
它运行一次,但视图不会自行更新(因为它是一个@Published
var)。即使我删除 @Published 它仍然运行两次。
我敢肯定这种行为有一个简单的解释,但我真的不知道是什么导致这种情况发生。
带有注释的代码中更好的解释:
风景:
struct MenuGroupBoxList: View {
@EnvironmentObject var session: SessionStore
var columns = [
GridItem(.adaptive(minimum: 100, maximum: 200), spacing: 8),
GridItem(.adaptive(minimum: 100, maximum: 200), spacing: 8)
]
var body: some View {
LazyVGrid(columns: columns, spacing: 8) {
ForEach(MenuTitles.allCases, id:\.self) { item in
if item == .sentShifts{
GroupColumn(menuItem: item, unit: Text(session.user?.totalShiftConsts.description ?? "0"))
}else if item == .weekdays{
//Deleting this line: session.user?.totalShifts.description. will run the loop once.
GroupColumn(menuItem: item, unit: Text(session.user?.totalShifts.description ?? "0"))
}else{
GroupColumn(menuItem: item, unit: Text("0"))
}
}
}.background(Color(UIColor.systemGroupedBackground))
}
}
foreach循环在哪里:
enum ChooseWeekdays{
case current, next
}
class WeekdaysModel: Identifiable, ObservableObject{
private var session = SessionStore.shared
private var date = Date()
@Published var week = [Day]()
@Published var isFetching = false
init(_ weekdays: ChooseWeekdays){
switch weekdays {
case .current:
currentWeekdaysFetch()
case .next:
nextWeekdaysFetch()
}
}
private func currentWeekdaysFetch(){
DispatchQueue.main.async {
self.isFetching = true
var count = 0
for (index, symbol) in self.date.weekDaySymbols.enumerated(){
let day = Day(date: self.date.currentWeek[index], isSelected: false, hasShifts: false, daySymbol: symbol, dayNumber: self.date.currentWeekNumbers[index])
day.setShifts(morning: self.session.employeesList, middle: self.session.employeesList, evening: self.session.employeesList)
if index == Date().getCurrentDayIndex(){
day.isSelected = true
}
count = count + day.shifts.compactMap({$0.employees.contains(where: {$0.uid == self.session.user?.uid})}).count
self.week.append(day)
self.isFetching = false
//Printing to see if loop run twice.
print("Index:", index)
}
//OR - take this line out from DispatchQueue, will run once but wouldn't update the UI because totalShifts is a @Published var
self.session.user?.totalShifts = count
}
}
}
我得到的打印结果是Index: 0...6
两次。
创建地点WeekdaysModel
:
struct WeekdaysView: View {
@ObservedObject var viewModel = WeekdaysModel(.current)
var body: some View {
ScrollView{
WeekRow(model: viewModel)
ForEach(viewModel.week){ day in
ShiftTypesView(day: day)
}
}
.navigationTitle(LocalizedStringKey("Weekdays"))
.background(Color(UIColor.systemGroupedBackground))
.edgesIgnoringSafeArea(.bottom)
}
}
在不同的文件中有另一个启动但不同的枚举(WeekdaysModel(.next)
)
解决方案
在 SwiftUI 上似乎很常见。我确实实验了类似的行为填充表格视图的单元格,每个单元格被调用两次:似乎 swiftUI 填充了每个查看的元素两次(我假设满足旋转)
正如建议的那样,从 swiftUI“视图构建”中填充数据结构一次(您的数据将被读取两次,但不会对数据库或网络进行两次昂贵的调用)
这种行为与 std UiKit 非常不同,如果涉及网络,可能会令人沮丧(调用将发出两次......双重网络完成,服务器错误(例如双重登录等......)
推荐阅读
- python - 无法使用 Rpy2 打印
- r - 在 ggplot 中使用 log10_trans() 时出错
- java - 如何使用带有 ConsoleLauncher 的命令行从 jar 中运行 Junit5 测试?
- javascript - 每次用户在本机中从一个屏幕移动到另一个屏幕时执行代码
- python - Python Profiling 问题,关于 exec_dynamic
- python - 蟒蛇 2.7。ImportError:没有名为 setuptools_rust 的模块和命令“python setup.py egg_info”失败,错误代码为 1
- vba - 在 DoCmd.TransferSpreadsheet 中对 sheetname 使用近似值
- pygame - 如何在 python 中分离图像块?
- linker - 无法将静态库添加到项目(之前遵循教程)
- python - 从文本数据集中提取特征