Swift Cocoa+Storyboard下反向传值设置NSToolbar的NSSlider
macOS端ViewController向WindowController反向传值更新NSToolbar滑块实现
针对你当前的代码结构,用闭包回调是改动最小、最易维护的实现方案,不需要引入复杂的通知或者代理逻辑,具体实现步骤如下:
第一步:修改ViewController代码
在ViewController中定义回调闭包,在总页数统计完成、当前页码变更时主动触发回调,把数据传给WindowController:
import Cocoa class ViewController: NSViewController { // 页码默认从1开始 var count: Int = 1 // 存储统计得到的客户总数量 var totalCustomerCount: Int = 0 // 页码/总页数更新回调:参数1为当前页码,参数2为总页数 var onPageInfoUpdate: ((_ currentPage: Int, _ totalPage: Int) -> Void)? @IBOutlet weak var myLabel: NSTextField! override func viewDidLoad() { super.viewDidLoad() // 执行原有客户数据库加载逻辑 loadCustomerData() } override var representedObject: Any? { didSet {} } // 你原有的客户数据加载逻辑 func loadCustomerData() { // 替换为你实际的数据库查询、总数量统计代码 totalCustomerCount = 100 count = 1 // 数据加载完成首次触发回调,同步滑块初始配置 onPageInfoUpdate?(count, totalCustomerCount) updatePageLabel() } func updateMyLabelText(newText: String){ if newText.contains("Prev") { // 页码边界判断,避免小于1 guard count > 1 else { return } count -= 1 } else if newText.contains("Next") { // 页码边界判断,避免超过总页数 guard count < totalCustomerCount else { return } count += 1 } // 页码变更后触发回调,同步工具栏状态 onPageInfoUpdate?(count, totalCustomerCount) updatePageLabel() } // 抽离页面内标签更新逻辑 func updatePageLabel() { myLabel.stringValue = "当前页码:\(count)/\(totalCustomerCount)" } }
第二步:修改WindowController代码
首先把XIB/Storyboard里工具栏的NSSlider、页码展示标签拖线为WindowController的输出口,在windowDidLoad中实现ViewController的回调逻辑,收到数据时直接更新工具栏控件:
import Cocoa class WindowController: NSWindowController { // 以下两个控件从Storyboard的工具栏拖线连接 @IBOutlet weak var pageSlider: NSSlider! @IBOutlet weak var pageLabel: NSTextField! @IBOutlet weak var myBoutton: NSToolbarItem! var viewController: ViewController { return self.window!.contentViewController! as! ViewController } override func windowDidLoad() { super.windowDidLoad() // 实现回调,接收ViewController回传的页码数据 viewController.onPageInfoUpdate = { [weak self] currentPage, totalPage in guard let self = self else { return } // 更新滑块的取值范围和当前值 self.pageSlider.minValue = 1 self.pageSlider.maxValue = Double(totalPage) self.pageSlider.doubleValue = Double(currentPage) // 更新工具栏页码标签 self.pageLabel.stringValue = "\(currentPage)/\(totalPage)" } } @IBAction func previous(_ sender: Any) { viewController.updateMyLabelText(newText: "Prev Button clicked! ") } @IBAction func next(_ sender: Any) { viewController.updateMyLabelText(newText: "Next Button clicked! ") } // 新增滑块拖动响应方法,连接NSSlider的valueChanged事件即可实现拖动滑块切页 @IBAction func sliderValueChanged(_ sender: NSSlider) { let targetPage = Int(sender.doubleValue.rounded()) viewController.count = targetPage // 这里补充你自己的对应页客户数据加载逻辑 viewController.updatePageLabel() } }
注意事项
- NSToolbar内的控件归WindowController持有,不要把相关输出口拖到ViewController中
- 必须加页码边界判断,避免页码值超出滑块取值范围导致异常
- 如果后续业务复杂度提升,需要多个模块监听页码变化,可以替换为
NotificationCenter发送全局通知,当前单页面场景闭包回调是最轻量的选择,没有不必要的性能开销
内容的提问来源于stack exchange,提问作者S Lareau
相关产品推荐
相关产品推荐

