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

SwiftUI Bug:ScrollView内LazyVGrid缓慢滚动时按钮标签异常

SwiftUI LazyVGrid 布局Bug(iOS 15/16)

这是一个在iOS 15、iOS 16系列多个版本真机和模拟器上均能复现的SwiftUI Bug,以下是详细信息:

复现代码

import SwiftUI

struct Item: Identifiable {
    let id: UUID
    let name: String
}

struct BugView: View {
    @State private var showGrid = false
    
    let items: [Item] = [
        .init(id: UUID(), name: "Addition"),
        .init(id: UUID(), name: "Subtraction"),
        .init(id: UUID(), name: "Multiplication"),
        .init(id: UUID(), name: "Division"),
        .init(id: UUID(), name: "Times Tables"),
        .init(id: UUID(), name: "Division Tables"),
        .init(id: UUID(), name: "Positive and negative numbers"),
        .init(id: UUID(), name: "Fractions"),
        .init(id: UUID(), name: "Add Fractions"),
        .init(id: UUID(), name: "Subtract Fractions"),
        .init(id: UUID(), name: "Multiply Fractions"),
        .init(id: UUID(), name: "Divide Fractions"),
        .init(id: UUID(), name: "Fractional Amount"),
        .init(id: UUID(), name: "Simplify Fractions"),
        .init(id: UUID(), name: "Convert to Fractions"),
        .init(id: UUID(), name: "Decimals"),
        .init(id: UUID(), name: "Add Decimals"),
        .init(id: UUID(), name: "Subtract Decimals"),
        .init(id: UUID(), name: "Multiply Decimals"),
        .init(id: UUID(), name: "Divide Decimals"),
        .init(id: UUID(), name: "Round Decimals"),
        .init(id: UUID(), name: "Convert to Decimals"),
        .init(id: UUID(), name: "Percentages"),
        .init(id: UUID(), name: "Percentages of Amount"),
        .init(id: UUID(), name: "Convert to Percentages"),
        .init(id: UUID(), name: "Exponents"),
        .init(id: UUID(), name: "Roots"),
        .init(id: UUID(), name: "Money"),
        .init(id: UUID(), name: "Add Money"),
        .init(id: UUID(), name: "Subtract Money"),
        .init(id: UUID(), name: "Multiply Money"),
        .init(id: UUID(), name: "Divide Money"),
        .init(id: UUID(), name: "Percentages of Money"),
        .init(id: UUID(), name: "Worksheets"),
        .init(id: UUID(), name: "Addition Worksheets"),
        .init(id: UUID(), name: "Multiplication Worksheets")
    ]

    var body: some View {
        if showGrid {
            ScrollView(.vertical) {
                LazyVGrid(columns: [GridItem(.adaptive(minimum: 160), spacing: 16, alignment: .top)], spacing: 16) {
                    ForEach(items) { item in
                        Button {
                            
                        } label: {
                            Text(verbatim: item.name)
                                .padding(48)
                        }
                        .buttonStyle(.plain)
                    }
                }
                .padding()
            }
        } else {
            Button {
                showGrid = true
            } label: {
                Text(verbatim: "Bug")
            }
        }
    }
}

@main
struct BugApp: App {
    var body: some Scene {
        WindowGroup {
            BugView()
        }
    }
}

Bug表现

  • 触发条件:通过@State变量切换到LazyVGrid视图后,缓慢滚动时间歇性出现
  • 症状:最后两个列表项无法显示/完成布局
  • 触发范围:仅当LazyVGrid内部嵌套Button或NavigationLink时出现,直接在ForEach中放置标签内容无此问题
  • 特殊表现:问题发生时,点击对应的NavigationLink,未显示的项会在跳转前突然出现
  • 排除场景:若@State变量showGrid初始设为true(无视图切换操作),该问题不会出现

已尝试无效的规避方案

  • 调整LazyVGrid的columns、spacing等参数
  • 添加fixedSize修饰符
  • 修改按钮样式
  • 为视图添加id标识
  • 移除内边距
  • 封装标签视图

推测原因

这是布局与ScrollView更新不及时导致的Bug,目前未找到相关官方文档或已知问题记录。使用.onTapGesture替代Button可规避,但不符合需求。

Bug演示

Bug演示

恳请各位提供解决方案或规避方法,谢谢!

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 18:14:53