Swift中如何将Home视图控制器的选中日期传递给浮动面板视图控制器
当然有好几种靠谱的方法能实现这个需求,我给你整理几个常用的方案,你可以根据项目的实际情况挑选:
方法1:直接给浮动面板视图控制器的属性赋值
这是最直接简单的方式,前提是你在HomeVC里已经持有了浮动面板VC的实例引用。
首先在你的浮动面板视图控制器里定义一个接收选中日期的属性:
class FloatingPanelVC: UIViewController { // 用来接收选中的日期字符串 var selectedDay: String? { didSet { // 可选:属性值变化时自动更新UI updateDateDisplay() } } private func updateDateDisplay() { guard let day = selectedDay else { return } // 这里更新你的UI元素,比如label.text = day } }
然后在HomeVC的日历选中方法里,直接给这个属性赋值:
func calendar(_ calendar: FSCalendar, didSelect date: Date, at monthPosition: FSCalendarMonthPosition) { log.success("date has been selected") day = formatter.string(from: date) // 假设你已经有浮动面板VC的实例引用,比如叫floatingPanelVC if let panelVC = floatingPanelVC as? FloatingPanelVC { panelVC.selectedDay = day } }
优点:实现简单,代码量少;缺点:需要HomeVC持有浮动面板VC的引用,若管理不当可能引发循环引用(记得用weak修饰引用)。
方法2:闭包回调
这种方式能实现更好的解耦,不需要HomeVC强持有浮动面板VC,适合大多数场景。
先在浮动面板VC里定义一个闭包属性:
class FloatingPanelVC: UIViewController { // 定义闭包,接收日期字符串参数 var onDateSelected: ((String) -> Void)? private func updateDateDisplay(_ dateString: String) { // 更新UI逻辑 } }
在HomeVC初始化或展示浮动面板的时候,给这个闭包赋值:
// 假设你在这里初始化浮动面板 let floatingPanelVC = FloatingPanelVC() // 用weak self避免循环引用 floatingPanelVC.onDateSelected = { [weak self] selectedDay in floatingPanelVC.updateDateDisplay(selectedDay) } // 之后用第三方库展示浮动面板,比如floatingPanel.set(contentViewController: floatingPanelVC)
然后在日历选中方法里触发闭包:
func calendar(_ calendar: FSCalendar, didSelect date: Date, at monthPosition: FSCalendarMonthPosition) { log.success("date has been selected") day = formatter.string(from: date) // 调用闭包传递日期 floatingPanelVC.onDateSelected?(day) }
优点:解耦性好,避免循环引用;缺点:逻辑稍微比直接赋值复杂一点,但胜在灵活。
方法3:代理模式
如果你的项目需要更规范的组件通信,或者未来可能有多个视图控制器需要监听日期选中事件,代理模式是个不错的选择。
首先定义一个代理协议:
protocol DateSelectionDelegate: AnyObject { func didSelectDate(_ dateString: String) }
在HomeVC里添加代理属性:
class HomeVC: UIViewController { // 用weak修饰避免循环引用 weak var dateSelectionDelegate: DateSelectionDelegate? func calendar(_ calendar: FSCalendar, didSelect date: Date, at monthPosition: FSCalendarMonthPosition) { log.success("date has been selected") day = formatter.string(from: date) // 通知代理 dateSelectionDelegate?.didSelectDate(day) } }
让浮动面板VC遵守这个协议,并设置自己为HomeVC的代理:
class FloatingPanelVC: UIViewController, DateSelectionDelegate { override func viewDidLoad() { super.viewDidLoad() // 假设HomeVC是当前浮动面板的presentingViewController或者父控制器 if let homeVC = presentingViewController as? HomeVC { homeVC.dateSelectionDelegate = self } } func didSelectDate(_ dateString: String) { // 更新UI updateDateDisplay(dateString) } private func updateDateDisplay(_ dateString: String) { // 处理UI更新逻辑 } }
优点:代码结构清晰,扩展性强;缺点:需要额外定义协议,适合有一定规模的项目。
方法4:NotificationCenter(通知中心)
如果HomeVC和浮动面板VC的层级关系比较复杂,或者你需要跨多个组件传递事件,可以用通知中心。
在HomeVC的日历选中方法里发送通知:
func calendar(_ calendar: FSCalendar, didSelect date: Date, at monthPosition: FSCalendarMonthPosition) { log.success("date has been selected") day = formatter.string(from: date) // 发送通知,传递日期字符串 NotificationCenter.default.post( name: NSNotification.Name("DateSelectedNotification"), object: day ) }
在浮动面板VC里监听通知,并在销毁时移除监听:
class FloatingPanelVC: UIViewController { override func viewDidLoad() { super.viewDidLoad() // 添加通知监听 NotificationCenter.default.addObserver( self, selector: #selector(handleDateSelected(_:)), name: NSNotification.Name("DateSelectedNotification"), object: nil ) } @objc private func handleDateSelected(_ notification: Notification) { if let selectedDay = notification.object as? String { updateDateDisplay(selectedDay) } } deinit { // 必须移除监听,避免内存泄漏 NotificationCenter.default.removeObserver(self) } private func updateDateDisplay(_ dateString: String) { // 更新UI逻辑 } }
优点:无需持有对方引用,跨层级通信方便;缺点:通知是全局的,容易引发命名冲突,且调试起来相对麻烦。
内容的提问来源于stack exchange,提问作者Samith Wijesinghe
相关产品推荐
相关产品推荐

