SwiftUI中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会因参数类型不匹配报错。
修复步骤
- 修改navigationDestination的闭包写法
将EventView中的错误行替换为显式闭包,手动创建EditEventView实例:
.navigationDestination(for: SwiftDataModel.self) { event in EditEventView(event: event) }
- 确保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()) // 全局注入 } } }
- 修复预览代码
给EventView的Preview添加必要的环境对象和模型容器,避免预览报错:
#Preview { EventView() .environmentObject(LocalNotificationManager()) .modelContainer(for: SwiftDataModel.self) }
EditEventView的预览也可以补充环境对象:
#Preview { NavigationStack { EditEventView(event: SwiftDataModel()) .environmentObject(LocalNotificationManager()) } }
内容的提问来源于stack exchange,提问作者Typical_0
相关产品推荐
相关产品推荐

