Linphone中MSList无法遍历:UnsafePointer不遵循Sequence协议
解决Linphone通话列表遍历的问题
这个问题很典型——Linphone的C API返回的MSList是它自定义的链表结构,并不是Swift原生的Sequence类型,所以直接用for-in循环肯定会报错。下面给你两种解决方案,从快速实现到优雅封装都有:
方案1:手动遍历MSList链表(快速上手)
MSList的结构很简单,每个节点包含data(指向LinphoneCall对象的指针)和next(指向下一个节点的指针)。我们可以手动循环遍历直到链表结束:
// 先获取通话列表的头节点 if let callsHead = linphone_core_get_calls(lc) { var currentNode = callsHead.pointee repeat { // 将data指针转换为LinphoneCall类型 if let call = currentNode.data?.assumingMemoryBound(to: LinphoneCall.self).pointee { // 获取并处理通话状态 let callState = linphone_call_get_state(call) print("通话状态:\(callState.rawValue)") // 这里可以根据状态做更多逻辑,比如区分来电/去电/已接通等 switch callState { case LinphoneCallStateIncomingReceived: print("收到来电") case LinphoneCallStateConnected: print("通话已接通") default: break } } // 移动到下一个节点,没有的话退出循环 guard let nextNodePtr = currentNode.next else { break } currentNode = nextNodePtr.pointee } while true }
重要提醒:线程安全
Linphone的核心对象可能在后台被修改,遍历的时候一定要加锁,避免竞态条件:
linphone_core_lock(lc) // 加锁 defer { linphone_core_unlock(lc) } // 确保退出时解锁 // 上面的遍历代码放在这里
方案2:封装成Swift Sequence(优雅复用)
如果需要多次遍历通话列表,可以给MSList扩展Sequence协议,以后就能直接用for-in了:
// 让MSList遵循Sequence协议 extension MSList: Sequence { public func makeIterator() -> MSListIterator { return MSListIterator(currentNode: self) } } // 实现迭代器 struct MSListIterator: IteratorProtocol { private var currentNode: MSList? init(currentNode: MSList) { self.currentNode = currentNode } mutating func next() -> LinphoneCall? { guard let node = currentNode else { return nil } // 转换为LinphoneCall对象 let call = node.data?.assumingMemoryBound(to: LinphoneCall.self).pointee // 移动到下一个节点 currentNode = node.next?.pointee return call } }
使用封装后的代码
现在遍历就像原生Swift集合一样简单:
linphone_core_lock(lc) defer { linphone_core_unlock(lc) } if let callsHead = linphone_core_get_calls(lc) { for call in callsHead.pointee { guard let validCall = call else { continue } let state = linphone_call_get_state(validCall) print("通话状态:\(state)") } }
这样以后不管哪里需要遍历Linphone的列表(比如聊天消息、联系人),都可以复用这个扩展啦。
内容的提问来源于stack exchange,提问作者user1079052
相关产品推荐
相关产品推荐

