You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 02:50:18