SwiftUI自定义CalendarLC组件如何兼容@ObservedObject与@State实现跨项目复用
实现跨项目复用的方案
核心逻辑
你当前的组件不可复用的核心原因是硬编码了业务模型ReservationsModel的依赖,只要把这层依赖解耦,用通用的状态绑定承接选中日期,就能兼容所有外部状态管理方式,不需要针对@State、@ObservedObject做单独适配。
具体实现
重构CalendarLC结构,内部仅保留通用的日期绑定和样式配置:
struct CalendarLC: View { // 用@Binding承接选中日期,不绑定任何具体业务模型 @Binding var selectedDate: Date // 通用样式配置保留 var axis: Axis.Set = .vertical var body: some View { // 你的原有日历逻辑,直接操作selectedDate即可 Text("当前选中日期:\(selectedDate.formatted(date: .abbreviated, time: .omitted))") } }
不同场景的调用方式
1. 原项目使用@ObservedObject管理状态
只要你的ReservationsModel中包含可读写的selectedDate属性,直接传入绑定即可:
@ObservedObject var viewModel: ReservationsModel // 调用组件 CalendarLC(selectedDate: $viewModel.selectedDate, axis: .vertical)
2. 其他项目使用@State管理状态
直接传入@State属性的绑定即可:
@State private var pickDate = Date() // 调用组件 CalendarLC(selectedDate: $pickDate)
适配说明
SwiftUI的@Binding本质是对值的读写引用,不关心值的存储来源:
@State修饰的属性可以通过$前缀获取Binding实例@ObservedObject、@EnvironmentObject修饰的对象的@Published属性,也可以通过$前缀获取对应属性的Binding实例
不需要额外定义特殊初始化,也不需要重复声明属性类型,组件可以直接适配所有场景。
如果需要支持组件自己管理选中日期、不需要外部传入状态的场景,可以新增一个便捷初始化:
extension CalendarLC { init(initialDate: Date = Date(), axis: Axis.Set = .vertical) { self._selectedDate = .init(get: { initialDate }, set: { _ in }) // 如果需要组件内部可修改选中日期,可以改为内部持有@State: // 首先把属性改成@State private var selectedDate: Date // 然后这个初始化里赋值 self._selectedDate = State(initialValue: initialDate) // 原有接受Binding的初始化保留即可 } }
内容的提问来源于stack exchange,提问作者kAiN
相关产品推荐
相关产品推荐

