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

SwiftUI中Picker关联TabView无法显示TaskHistoryView的问题及修复

问题原因与修复方案

核心原因

  1. 子组件状态声明错误:TaskHistoryView中用@State声明activities,但@State仅用于管理组件内部状态,会忽略外部传入的初始值,且父组件数据更新时无法同步到子组件,导致子组件始终显示空列表。
  2. 滚动容器嵌套布局冲突:TabView(自带滚动特性)嵌套在ScrollView中,SwiftUI无法正确计算TabView的高度,内容被挤压无法显示。
  3. TabView选项不完整:Picker包含两个标签,但TabView仅实现了tag0的视图,虽不是当前标签0不显示的直接原因,但会导致切换到tag1时空白。

修复步骤

1. 修正TaskHistoryView的变量声明

将子组件中用于接收外部数据的@State改为普通let(仅展示数据无需内部修改):

struct TaskHistoryView: View {
    
    @Environment(\.dismiss) var dismiss
    let activities: [TaskActivity] // 替换@State为let
    
    var body: some View {
        ZStack {
            VStack(spacing: 0) {
                List {
                    ForEach(0..<(activities.count), id: \.self) { i in
                        let data = activities[i]
                        HStack {
                            VStack(alignment: .leading, spacing: 4) {
                                Text("\(data.name ?? "") \(data.activity ?? "")")
                                    .font(.calibriRegular(with: 16))
                                    .foregroundStyle(Color(hex: 0x272A2C))
                                Text(data.actionOn ?? "")
                                    .font(.calibriRegular(with: 12))
                                    .foregroundStyle(Color.hex9FA297)
                            }
                            Spacer()
                        }
                        .padding(10)
                        .background(
                            Color.white
                                .clipShape(RoundedRectangle(cornerRadius: 8))
                                .shadow(color: Color(hex: 0x3C4441, alpha: 0.08), radius: 4, x: 0, y: 0)
                        )
                    }
                    .listRowInsets(EdgeInsets())
                }
                .listStyle(.plain)
            }
        }
    }
}

2. 解决滚动容器嵌套问题

调整布局结构,将TabView移出外层ScrollView,避免嵌套滚动容器,让TabView占据剩余屏幕空间:

struct TaskManagementDetailsView: View {
    
    @State var data: TaskManagementData? = nil
    @State var activities: [TaskActivity] = []
    @StateObject private var viewModel = TaskManagementViewModel()
    
    @State private var selectedTab: Int = 0
    var selectedTabVal = 0
    
    var body: some View {
        ZStack {
            Color.hexF4F4FC
                .ignoresSafeArea()
            VStack(spacing: 0) {
                // 顶部任务信息用ScrollView包裹
                ScrollView {
                    VStack(alignment: .leading) {
                        Text(data?.taskList ?? "Test")
                        
                        VStack(alignment: .leading) {
                            Text("Assigned to")
                                .font(.calibriBold(with: 16))
                        }
                        .padding(.vertical, 10)
                        
                        VStack(alignment: .leading) {
                            Text("Start Date")
                                .font(.calibriBold(with: 16))
                            Text(data?.startDate ?? "")
                                .font(.calibriRegular(with: 16))
                                .foregroundStyle(Color.black.opacity(0.7))
                        }
                        
                        VStack(alignment: .leading) {
                            Text("Assign By:")
                                .font(.calibriBold(with: 16))
                            Text(data?.assignBy ?? "")
                                .font(.calibriRegular(with: 16))
                                .foregroundStyle(Color.black.opacity(0.7))
                        }
                        
                        // Picker放在顶部ScrollView内
                        VStack {
                            Picker("", selection: $selectedTab) {
                                Text("History")
                                    .tag(0)
                                Text("Comments")
                                    .tag(1)
                            }
                            .pickerStyle(.segmented)
                            .padding(.horizontal)
                            .padding(.top, 2)
                            .padding(.bottom, 10)
                        }
                        .background(Color.appGreen2)
                        .padding(.bottom, 10)
                    }
                    .padding(.horizontal)
                    .padding(.top, 20)
                }
                
                // TabView独立占据剩余空间
                TabView(selection: $selectedTab) {
                    TaskHistoryView(activities: activities)
                        .padding()
                        .tag(0)
                    // 补充tag1的Comments视图
                    VStack {
                        Text("Comments Section")
                        // 替换为你的自定义Comments视图
                    }
                    .tag(1)
                }
                .tabViewStyle(.page(indexDisplayMode: .never))
                .animation(.default, value: selectedTab)
                .frame(maxHeight: .infinity)
            }
        }
        .onAppear {
            if let id = data?.id {
                viewModel.fetchTasksDetails(id: id) { status, data in
                    if status {
                        if let task = data?.task {
                            self.data = task
                        }
                        self.activities = data?.activities ?? []
                        print("Activities: \(self.activities)")
                        selectedTab = selectedTabVal
                    }
                }
            }
        }
    }
}

3. 可选:优化List的ForEach写法

建议直接遍历activities数组(需确保TaskActivity遵循Identifiable协议),让代码更简洁且符合SwiftUI最佳实践:

// 先让TaskActivity遵循Identifiable
struct TaskActivity: Identifiable {
    let id: UUID // 或你的自定义唯一ID
    var name: String?
    var activity: String?
    var actionOn: String?
    // 其他属性
}

// 然后在TaskHistoryView中修改ForEach
ForEach(activities) { data in
    HStack {
        VStack(alignment: .leading, spacing: 4) {
            Text("\(data.name ?? "") \(data.activity ?? "")")
                .font(.calibriRegular(with: 16))
                .foregroundStyle(Color(hex: 0x272A2C))
            Text(data.actionOn ?? "")
                .font(.calibriRegular(with: 12))
                .foregroundStyle(Color.hex9FA297)
        }
        Spacer()
    }
    .padding(10)
    .background(
        Color.white
            .clipShape(RoundedRectangle(cornerRadius: 8))
            .shadow(color: Color(hex: 0x3C4441, alpha: 0.08), radius: 4, x: 0, y: 0)
    )
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 04:27:02