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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.28 10:59:07