BLE设备追踪App:AppDelegate调用ViewController刷新TableView无效问题
解决BLE设备追踪App中AppDelegate调用ViewController刷新无效的问题
我来帮你排查这个头疼的问题!这种情况十有八九是你在AppDelegate里调用的ViewController实例不是当前屏幕上正在显示的那个,所以刷新方法根本没作用到正确的界面上。下面是具体的分析和解决方案:
1. 先确认核心问题:实例不匹配
很多开发者会犯一个错误——直接在AppDelegate里new一个ViewController对象(比如let vc = ViewController()),但这个新创建的实例和导航栈里已经显示的VC完全是两个独立的对象,调用它的方法自然不会影响到实际界面。
你可以做个简单测试:
- 在ViewController的
viewDidLoad里加一句print("当前VC实例地址:", self) - 在AppDelegate里调用刷新方法前,也打印一下你拿到的VC实例地址
对比两个地址,如果不一样,那就是实例不匹配的问题,接下来看正确的获取方式。
2. 正确的解决方案
方案一:获取当前显示的ViewController实例
通过AppDelegate获取窗口的根控制器,层层找到当前活跃的ViewController:
// 在AppDelegate中添加这个方法 private func getCurrentVisibleViewController() -> ViewController? { guard let rootVC = UIApplication.shared.keyWindow?.rootViewController else { return nil } var currentVC = rootVC // 找到最上层的presented控制器 while let presented = currentVC.presentedViewController { currentVC = presented } // 如果是导航控制器,取topViewController if let navVC = currentVC as? UINavigationController { return navVC.topViewController as? ViewController } else { return currentVC as? ViewController } }
然后在蓝牙发现设备的回调里这样调用:
// 发现BLE设备后 if let targetVC = getCurrentVisibleViewController() { targetVC.refreshTableView() }
方案二:用通知中心解耦(更推荐)
这种方式不需要AppDelegate直接持有ViewController的引用,代码解耦性更强,也避免了实例匹配的问题:
- 在ViewController里注册通知:
override func viewDidLoad() { super.viewDidLoad() // 注册刷新列表的通知 NotificationCenter.default.addObserver( self, selector: #selector(refreshTableView), name: NSNotification.Name(rawValue: "BLEDeviceListNeedsRefresh"), object: nil ) } // 记得在销毁时移除通知,防止内存泄漏 deinit { NotificationCenter.default.removeObserver(self) }
- 在AppDelegate的蓝牙回调里发送通知:
// 发现新设备后发送通知 NotificationCenter.default.post( name: NSNotification.Name(rawValue: "BLEDeviceListNeedsRefresh"), object: nil )
3. 额外必查细节
- 确保刷新操作在主线程执行:蓝牙回调通常在后台线程,而UI操作必须在主线程,所以你的
refreshTableView方法要这么写:
@objc func refreshTableView() { DispatchQueue.main.async { self.tableView.reloadData() } }
- 检查数据源是否同步:如果AppDelegate更新了设备列表,但ViewController的数据源数组没有同步更新,就算调用
reloadData也不会有变化。可以考虑把设备列表放在一个全局单例里,或者通过通知把新设备数据传递给ViewController。
内容的提问来源于stack exchange,提问作者Danf
相关产品推荐
相关产品推荐

