Swift中使用PubNub订阅带用户在线状态的频道并实现上下线实时监听
PubNub 在线状态自动回调实现方案
现有代码问题
你已经开启了通道的presence订阅,但是创建的SubscriptionListener没有绑定到PubNub实例,同时作为局部变量会在方法执行结束后被释放,所以无法收到自动触发的上下线事件回调,才需要手动调用hereNow查询状态。
修复实现要点
- 将
SubscriptionListener声明为类的成员属性,避免局部作用域回收 - 调用
pubnub.add(listener)将监听器绑定到PubNub实例,触发回调生效 - 仅首次进入房间时调用
hereNow拉取全量在线用户,后续上下线变动通过presenceChanged回调自动更新,无需重复手动查询
修复后参考代码
// 声明为类成员属性,避免被提前释放 private var presenceListener: SubscriptionListener? func registerForConnectRoom(roomId: String) { let channelId = "ch:callroom:" + roomId pubnub.subscribe(to: [channelId], withPresence: true) presenceListener = SubscriptionListener() presenceListener?.didReceiveSubscription = { [weak self] event in switch event { case let .messageReceived(message): print("收到消息: \(message)") case let .connectionStatusChanged(status): print("连接状态变更: \(status)") case let .presenceChanged(presence): // 这里会自动触发上下线事件,不需要手动调用hereNow print("Presence事件触发: \(presence)") // 从presence对象直接获取变动用户和当前在线信息 switch presence.event { case .join: print("\(presence.uuid ?? "未知用户") 进入房间") // 直接更新你的在线用户列表 case .leave: print("\(presence.uuid ?? "未知用户") 主动离开房间") case .timeout: print("\(presence.uuid ?? "未知用户") 掉线离开房间") default: break } // 直接获取当前通道在线人数 print("当前房间在线人数: \(presence.occupancy)") case let .subscribeError(error): print("订阅出错: \(error)") default: break } } // 核心步骤:将监听器绑定到PubNub实例才会收到回调 if let listener = presenceListener { pubnub.add(listener) } // 仅首次进入房间时调用一次hereNow拉取初始全量在线用户 hereNow(roomId: roomId) } func hereNow(roomId: String) { let channelId = "ch:callroom:" + roomId pubnub.hereNow(on: [channelId], includeState: true) { result in switch result { case let .success(presenceByChannel): if let myChannelPresence = presenceByChannel[channelId] { print("房间初始在线人数: \(myChannelPresence.occupancy)") print("房间初始在线用户列表: \(myChannelPresence.occupants)") // 这里初始化你的在线用户列表即可 } case let .failure(error): print("拉取初始在线列表失败: \(error.localizedDescription)") } } } // 页面销毁时移除监听器、取消订阅避免内存泄漏 deinit { if let listener = presenceListener { pubnub.remove(listener) } pubnub.unsubscribeAll() }
补充说明
presence事件会在用户加入、主动离开、掉线超过心跳超时时间时自动触发,无需轮询调用hereNow,能完全满足你需要的自动上下线回调需求。
内容的提问来源于stack exchange,提问作者user10469417
相关产品推荐
相关产品推荐

