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

如何判断SwiftUI视图重绘完成?解决SwiftData列表滚动失效问题

解决SwiftData添加数据后无法滚动到新项的问题

问题核心是SwiftData插入数据后,视图更新是异步的,你设置selectedRecipe时,列表还没完成新数据的加载渲染,导致scrollTo找不到对应的ID。以下是几个可行的解决办法:

方法一:监听食谱列表更新后触发滚动

利用.onChange(of: recipes)监听食谱数组的变化,等列表完成更新后,再检查当前selectedRecipe是否存在并执行滚动;同时保留对selectedRecipe的监听,处理手动选择的滚动场景:

ScrollViewReader { proxy in
    List(self.recipes, id: \.id, selection: $selectedRecipe) { recipe in
        RecipeCellView(recipe: recipe)
    }
    .focusable()
    .onAppear() {
        if !recipes.isEmpty {
            selectedRecipe = recipes[0].id
        }
    }
    // 处理手动选择食谱的滚动
    .onChange(of: selectedRecipe) { new in
        guard let newId = new, recipes.contains(where: { $0.id == newId }) else { return }
        proxy.scrollTo(newId, anchor: .top)
    }
    // 列表更新后,确保新添加的项已加载再滚动
    .onChange(of: recipes) { _ in
        guard let selectedId = selectedRecipe else { return }
        proxy.scrollTo(selectedId, anchor: .top)
    }
}

方法二:结合.task修饰符等待视图更新完成

使用.task(id: selectedRecipe),当selectedRecipe变化时启动任务,利用SwiftUI的视图周期特性,确保列表已完成更新后再执行滚动:

ScrollViewReader { proxy in
    List(self.recipes, id: \.id, selection: $selectedRecipe) { recipe in
        RecipeCellView(recipe: recipe)
    }
    .focusable()
    .onAppear() {
        if !recipes.isEmpty {
            selectedRecipe = recipes[0].id
        }
    }
    .task(id: selectedRecipe) {
        guard let newId = selectedRecipe else { return }
        proxy.scrollTo(newId, anchor: .top)
    }
}

方法三:保存模型上下文后再更新选中状态

在addRecipe方法中先保存模型上下文,等新数据持久化并被视图加载后,再设置selectedRecipe:

func addRecipe() {
    let myRecipe = Recipe()
    modelContext.insert(myRecipe)
    
    do {
        try modelContext.save()
        selectedRecipe = myRecipe.id
    } catch {
        print("保存食谱失败:\(error.localizedDescription)")
    }
}

另外注意代码细节:详情视图使用searchResults,主视图用recipes,需确保两个数组数据源一致,避免选中的食谱在详情中找不到的问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 06:27:40