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

SwiftUI中NavigationDestination结合EnvironmentObject的类型错误求助

问题:NavigationDestination传递EnvironmentObject时类型不匹配错误

我正在开发一款学习类App,使用SwiftData存储“event”数据,通过NavigationDestination实现跳转到EditEventView进行event编辑,同时集成了本地通知功能。在EditEventView中使用EnvironmentObject传递LocalNotificationManager后,EventView中出现如下错误:

Cannot convert value of type '(SwiftDataModel, EnvironmentObject, Environment) -> EditEventView' to expected argument type '(SwiftDataModel) -> EditEventView'

相关代码

EventView:

import SwiftUI
import SwiftData
import UserNotifications

struct EventView: View {
    @Environment(\.modelContext) var modelContext
    @Query var events: [SwiftDataModel]
    @State private var path = [SwiftDataModel]()
    var body: some View {
        NavigationStack(path: $path) {
            List {
                ForEach(events) { event in
                    NavigationLink(value: event) {
                        VStack(alignment: .leading) {
                                Text(event.nameOfSession)
                                    .font(.headline)
                                Text(event.date.formatted(date: .long, time: .shortened))
                        }
                    }
                }
                .onDelete(perform: deleteDistractions)
                .listRowBackground(Color(.systemGray6))
            }
            .onAppear {
                        UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .badge, .sound]) { success, error in
                            if success {
                                print ("All Set!")
                            } else if let error = error {
                                print(error.localizedDescription)
                            }
                        }
                    }
            .background(.white)
            .scrollContentBackground(.hidden)
            .navigationTitle("Your Sessions")
// 错误行
            **.navigationDestination(for: SwiftDataModel.self, destination: EditEventView.init)** 
            .toolbar {
                Button{
                    addDistraction()
                } label: {
                    Image(systemName: "plus.circle.fill")
                }
            }
        }
    }
    
    // MARK: Swift Data model functions
    
    // 添加学习会话数据到模型
    func addDistraction() {
        let event = SwiftDataModel()
        modelContext.insert(event)
        path = [event]
    }
    
    // 从模型删除学习会话数据
    func deleteDistractions( indexSet: IndexSet) {
        for index in indexSet {
            let event = events[index]
            modelContext.delete(event)
            }
        }
}

#Preview {
    EventView()
}

EditEventView:

import SwiftUI
import SwiftData

struct EditEventView: View {
    @Bindable var event: SwiftDataModel
    @EnvironmentObject var lnManager: LocalNotificationManager
    @Environment(\.scenePhase) var scenePhase
    var body: some View {
        VStack {
            Form {
                TextField("Name", text: $event.name_of_event)
                
                Picker("Work recording metheod", selection: $event.subject_type) {
                    Text ("Other").tag(EventType.other)
                    Text ("English").tag(EventType.english)
                    Text ("Humanities").tag(EventType.humanities)
                    Text ("Maths").tag(EventType.maths)
                    Text ("Sciance").tag(EventType.sciance)
                    
                }
                .pickerStyle(.menu)
                
                DatePicker("Session Date", selection: $event.event_date)
                    .datePickerStyle(CompactDatePickerStyle())
                    .frame(maxHeight: 400)
                
                Toggle("Notifications", isOn: $event.is_notified)
            }
            .navigationTitle("Add Session")
            .navigationBarTitleDisplayMode(.inline)
            .onAppear {
                event.date = Date.now
            }
            Button{
                if event.is_notified {
                    Task {
                        let dateComponents = Calendar.current.dateComponents([.month, .day, .hour, .minute], from: event.event_date)
                        let localNotification = LocalNotification(identifier: UUID().uuidString, title: "Its study time!", body: "Looks like your studying \(event.subject_type.rawValue)", repeats: false, dateComponents: dateComponents)
                        await lnManager.schedule(localNotification: localNotification)
                    }
                }
            } label: {
                Text ("Add Event")
            }
            .buttonStyle(.borderedProminent)
        }
    }
}

解决方案

问题原因

EditEventView中声明了@EnvironmentObject var lnManager: LocalNotificationManager和@Environment(\.scenePhase) var scenePhase,这两个属性会让Swift自动生成包含这些环境参数的初始化方法,导致EditEventView的初始化不再是仅接受SwiftDataModel的单一参数。而navigationDestination期望的是一个仅接收SwiftDataModel的闭包,直接传递EditEventView.init会因参数类型不匹配报错。

修复步骤

  1. 修改navigationDestination的闭包写法
    将EventView中的错误行替换为显式闭包,手动创建EditEventView实例:
.navigationDestination(for: SwiftDataModel.self) { event in
    EditEventView(event: event)
}
  1. 确保LocalNotificationManager已全局注入
    在App的根视图层级(比如YourApp.swift)中注入LocalNotificationManager,确保EditEventView能通过@EnvironmentObject获取到该实例:
@main
struct YourStudyApp: App {
    let container: ModelContainer
    
    init() {
        do {
            container = try ModelContainer(for: SwiftDataModel.self)
        } catch {
            fatalError("Failed to initialize ModelContainer: \(error)")
        }
    }
    
    var body: some Scene {
        WindowGroup {
            EventView()
                .modelContainer(container)
                .environmentObject(LocalNotificationManager()) // 全局注入
        }
    }
}
  1. 修复预览代码
    给EventView的Preview添加必要的环境对象和模型容器,避免预览报错:
#Preview {
    EventView()
        .environmentObject(LocalNotificationManager())
        .modelContainer(for: SwiftDataModel.self)
}

EditEventView的预览也可以补充环境对象:

#Preview {
    NavigationStack {
        EditEventView(event: SwiftDataModel())
            .environmentObject(LocalNotificationManager())
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 20:25:18