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

SwiftUI数组ForEach循环中NavigationLink按钮报错及跳转问题

SwiftUI问题解决:根据模型创建跳转链接并修复初始化错误

错误原因分析

你遇到的Argument passed to call that takes no arguments错误,根源有两个:

  1. 错误实例化模型而非视图:代码中NavigationLink(destination: Meditation(array: meditation))是错误的——Meditation是你的数据模型结构体,不是用来展示内容的View,你需要创建一个专门的详情页View来接收并展示Meditation数据。
  2. NavigationLink使用位置错误:SwiftUI的NavigationLink是View类型,不能放在Button的action闭包中执行(闭包仅处理事件逻辑,不负责添加View到视图层级)。

分步解决方案

1. 创建详情页View

先定义一个接收Meditation模型的详情View,用于展示对应内容:

struct MeditationDetailView: View {
    let meditation: Meditation
    
    var body: some View {
        VStack(spacing: 20) {
            Image(meditation.imageName)
                .resizable()
                .scaledToFit()
                .frame(height: 200)
            Text(meditation.title)
                .font(.title)
                .fontWeight(.bold)
            Text(meditation.desc)
                .font(.body)
                .foregroundColor(.secondary)
        }
        .padding()
        .navigationTitle(meditation.title)
    }
}

2. 修复ContentView的跳转逻辑

推荐使用绑定变量+隐藏NavigationLink的方式,既满足点击卡片的逻辑判断,又符合SwiftUI的视图层级规则:

struct ContentView: View {
    @EnvironmentObject var userViewModel: UserViewModel
    @State var isPaywallPresented = false
    @State private var selectedMeditation: Meditation? // 存储选中的模型
    
    var body: some View {        
        TabView {            
            NavigationView {
                ScrollView (showsIndicators: false) {
                    VStack (alignment: .leading, spacing: 20) {
                        ForEach(Meditation.getSampleMeditations()) { meditation in
                            Button {
                                // 点击卡片时判断订阅状态
                                if userViewModel.isSubscriptionActive {
                                    selectedMeditation = meditation // 选中模型,触发跳转
                                } else {
                                    isPaywallPresented = true // 弹出付费墙
                                }
                            } label: {
                                Card(meditation: meditation)
                            }
                        }
                    }
                    .padding()
                    .navigationTitle("Meditations")
                    
                    // 隐藏的NavigationLink,通过绑定变量控制跳转
                    .background(
                        NavigationLink(
                            destination: selectedMeditation.map { MeditationDetailView(meditation: $0) },
                            isActive: Binding(
                                get: { selectedMeditation != nil },
                                set: { if !$0 { selectedMeditation = nil } }
                            )
                        ) {
                            EmptyView()
                        }
                    )
                }
            }
            // 弹出付费墙
            .sheet(isPresented: $isPaywallPresented) {
                PaywallView() // 替换成你的付费墙视图
            }
        }
    }
}

3. 优化Meditation模型的初始化(可选)

把模型的属性改成不可变的,并添加便捷初始化,让示例数据的创建更简洁:

struct Meditation: Identifiable {
    let id = UUID()
    let title: String
    let desc: String
    let imageName: String
    let productId: String?
    
    static func getSampleMeditations() -> [Meditation] {
        [
            Meditation(title: "GP Calculator", desc: "Simple GP Calculator", imageName: "ambition", productId: "ambition"),
            // 可添加更多示例数据
        ]
    }
}

另一种实现方式(直接用NavigationLink)

如果你更倾向于直接用NavigationLink包裹卡片,可以通过手势判断订阅状态,同时禁用未订阅时的跳转:

ForEach(Meditation.getSampleMeditations()) { meditation in
    NavigationLink(destination: MeditationDetailView(meditation: meditation)) {
        Card(meditation: meditation)
    }
    // 点击时判断订阅状态,未订阅则弹出付费墙
    .simultaneousGesture(
        TapGesture().onEnded {
            if !userViewModel.isSubscriptionActive {
                isPaywallPresented = true
            }
        }
    )
    // 未订阅时禁用跳转
    .disabled(!userViewModel.isSubscriptionActive)
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 19:51:02