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

SwiftUI异步加载List时出现动画闪烁重复渲染Bug如何解决?

问题根因

该闪烁问题由状态更新时序错误导致:你在搜索关键词变化时先立即切换searchByWordView = false进入搜索结果展示状态,再异步请求新的搜索结果。在异步请求的间隙,List会先渲染FoodList中存储的上一次搜索旧数据,等新请求结果返回后才会刷新为新内容,因此出现了旧列表短暂闪现的问题。

修复步骤

1. 新增状态变量

在ContentView中新增两个状态变量,用于控制搜索流程和取消无效请求:

@State private var isSearching: Bool = false
@State private var currentSearchTask: Task<Void, Never>?

2. 调整搜索触发逻辑

修改selectedFood的onChange回调,调整状态更新顺序,等搜索结果返回后再切换到搜索结果展示状态:

.onChange(of: selectedFood, perform: { keyword in
    // 取消上一次未完成的搜索请求
    currentSearchTask?.cancel()
    
    if keyword.isEmpty {
        searchByWordView = true
        FoodList.removeAll()
        isSearching = false
        return
    }
    
    isSearching = true
    currentSearchTask = Task {
        // 可选:添加300ms防抖,减少输入过程中的请求次数
        try? await Task.sleep(nanoseconds: 300_000_000)
        guard !Task.isCancelled, selectedFood == keyword else { return }
        
        let newSearchResult = await GetFoodItemsByName(_name: keyword)
        guard !Task.isCancelled, selectedFood == keyword else { return }
        
        FoodList = newSearchResult
        searchByWordView = false
        isSearching = false
    }
})

3. 优化列表展示逻辑

给列表添加搜索中状态的展示,避免请求过程中出现空白或者旧内容:

List {
    if isSearching {
        Section {
            HStack(spacing: 8) {
                Spacer()
                ProgressView()
                Text("搜索中...")
                Spacer()
            }
            .padding(.vertical, 12)
        }
    } else if !searchByWordView {
        Section {
            ForEach(FoodList, id:\.self){ item in
                Button(action: {
                    selectedFoodTemp = item.name
                    addScreen.toggle()
                }){
                    Text(item.name)
                }
                .foregroundColor(.black)
            }
        }
    } else {
        Section {
            ForEach(FoodCList, id:\.self){ category in
                NavigationLink(destination: GetFoodCategoryItemsView(category: category.name)) {
                    Text(category.name)
                }
                .foregroundColor(.black)
            }
        }
    }
}

修改完成后即可解决列表闪烁的问题,同时还优化了快速输入时的请求性能,避免无效请求浪费资源。


内容的提问来源于stack exchange,提问作者Isaac

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 18:15:02