SwiftUI中如何将多个nextPerson变量转为数组实现循环复用?
问题描述
我通过以下方式对PersonsDatabase数组进行排序:
@Query(sort: \PersonsDatabase.number) var Persons: [PersonsDatabase]
我想要实现一个人员列表数组,每次按下按钮时该数组会递减一项,起始值由以下代码控制:
@State private var nextIndex: Int = -1
目前我使用以下变量来展示每一行数据:
@State private var nextPerson: PersonsDatabase? @State private var nextPerson1: PersonsDatabase? @State private var nextPerson2: PersonsDatabase? @State private var nextPerson3: PersonsDatabase? ...
并通过以下逻辑为每个变量赋值:
nextIndex += 1 print("Next Index:\(nextIndex)") print("Numbers:\(numbers.count)") if numbers.count >= 1 { if nextIndex < numbers.count, let next = Persons.first(where: { $0.number == numbers[nextIndex] }) { nextPerson = next } else { nextPerson = nil } } if numbers.count >= 2 { if nextIndex < numbers.count-1, let next = Persons.first(where: { $0.number == numbers[nextIndex+1] }) { nextPerson1 = next } else { nextPerson1 = nil } } ...
这种写法可行但过于繁琐,请问能否将这些nextPerson变量转为数组,从而通过循环实现逻辑复用?
解决方案
完全可以把分散的nextPerson变量替换成数组来简化代码,通过循环批量处理赋值逻辑,彻底避免重复代码。
1. 替换单个变量为数组
把原来的多个nextPersonX变量改成一个数组,可根据你需要展示的最大数量初始化:
// 示例:最多展示4项,初始化为4个nil @State private var displayedPersons: [PersonsDatabase?] = Array(repeating: nil, count: 4)
2. 用循环重构赋值逻辑
修改按钮点击后的逻辑,通过循环批量处理每个位置的人员赋值:
nextIndex += 1 print("Next Index:\(nextIndex)") print("Numbers:\(numbers.count)") // 定义最大展示数量,可根据需求调整 let maxDisplayCount = 4 // 先重置数组,保证长度匹配最大展示数 displayedPersons = Array(repeating: nil, count: maxDisplayCount) for offset in 0..<maxDisplayCount { let targetIndex = nextIndex + offset // 检查索引是否在numbers的有效范围内 guard targetIndex < numbers.count else { continue } // 根据number匹配对应的人员对象 if let person = Persons.first(where: { $0.number == numbers[targetIndex] }) { displayedPersons[offset] = person } }
3. 遍历数组渲染视图
在SwiftUI视图中,直接遍历displayedPersons数组展示每一行:
VStack { ForEach(displayedPersons.indices, id: \.self) { index in if let person = displayedPersons[index] { Text("\(person.number) - \(person.name)") // 替换为你的人员属性展示逻辑 } else { Text("暂无数据") // 无人员时的占位文本 } } Button("加载下一组") { // 调用上述赋值逻辑 } }
额外性能优化
如果Persons数组是按number排序的,可以提前生成number到PersonsDatabase的字典映射,避免每次调用first(where:)遍历数组:
// 假设number是Int类型,根据实际类型调整 private var personMap: [Int: PersonsDatabase] { Dictionary(uniqueKeysWithValues: Persons.map { ($0.number, $0) }) } // 循环中直接通过字典查找 if let person = personMap[numbers[targetIndex]] { displayedPersons[offset] = person }
这样调整后,不管需要展示多少项,只需修改maxDisplayCount的值即可,逻辑代码无需重复编写,大幅降低维护成本。
内容的提问来源于stack exchange,提问作者Edward Hasted
相关产品推荐
相关产品推荐

