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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 07:39:44