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

Multipeer Connectivity框架中无法显示数据传输进度的技术问询

如何在Multipeer Connectivity中打印传输进度

不管是接收端还是发送端,Multipeer Connectivity都提供了Progress对象来追踪传输状态,但直接打印对象本身看不到直观的进度数值,我来给你优化下实现方式:

接收端优化实现

你当前的didStartReceivingResourceWithName方法已经拿到了进度对象,但直接print(progress)只会输出对象的类信息。推荐两种更实用的方式:

方式1:使用Progress的进度回调闭包(Swift 4.2+推荐)

这种方式不用手动处理KVO,代码更简洁安全:

func session(_ session: MCSession, didStartReceivingResourceWithName resourceName: String, fromPeer peerID: MCPeerID, with progress: Progress) {
    // 设置进度回调,每次进度更新都会触发这个闭包
    progress.setProgressHandler { [weak self] progress in
        // 回到主线程操作(如果要更新UI也在这里)
        DispatchQueue.main.async {
            let percentage = progress.fractionCompleted * 100
            print("从\(peerID.displayName)接收\(resourceName)进度:\(String(format: "%.2f", percentage))%")
            // 也可以查看字节数详情
            print("已接收:\(progress.completedUnitCount)/\(progress.totalUnitCount) 字节")
        }
    }
}

方式2:KVO监听进度变化(兼容旧版本Swift)

如果你的项目需要兼容更早的Swift版本,可以用KVO:

func session(_ session: MCSession, didStartReceivingResourceWithName resourceName: String, fromPeer peerID: MCPeerID, with progress: Progress) {
    // 添加KVO监听fractionCompleted属性的变化
    progress.addObserver(self, forKeyPath: #keyPath(Progress.fractionCompleted), options: [.new], context: nil)
}

// 实现KVO回调方法
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
    guard keyPath == #keyPath(Progress.fractionCompleted), let progress = object as? Progress else {
        super.observeValue(forKeyPath: keyPath, of: object, change: change, context: context)
        return
    }
    
    DispatchQueue.main.async {
        let percentage = progress.fractionCompleted * 100
        print("实时接收进度:\(String(format: "%.2f", percentage))%")
    }
}

// 别忘了在接收完成后移除观察者,避免内存泄漏
func session(_ session: MCSession, didFinishReceivingResourceWithName resourceName: String, fromPeer peerID: MCPeerID, at localURL: URL?, withError error: Error?) {
    // 这里需要你保存对应的Progress对象,或者通过其他方式关联到当前接收任务
    // 示例:假设你用字典保存了peerID和Progress的映射
    if let progress = progressMap[peerID] {
        progress.removeObserver(self, forKeyPath: #keyPath(Progress.fractionCompleted))
        progressMap.removeValue(forKey: peerID)
    }
}

发送端实现

发送端调用sendResource时会直接返回Progress对象,处理方式和接收端一致:

闭包方式(推荐)

// 假设你要发送本地文件
let targetPeer = // 目标MCPeerID
let fileURL = URL(fileURLWithPath: "/path/to/your/file")
let resourceName = "my_file.txt"

// 发送资源并获取进度对象
let sendProgress = session.sendResource(at: fileURL, withName: resourceName, toPeer: targetPeer)

// 设置进度回调
sendProgress.setProgressHandler { progress in
    DispatchQueue.main.async {
        let percentage = progress.fractionCompleted * 100
        print("向\(targetPeer.displayName)发送\(resourceName)进度:\(String(format: "%.2f", percentage))%")
        print("已发送:\(progress.completedUnitCount)/\(progress.totalUnitCount) 字节")
    }
}

KVO方式

和接收端的KVO逻辑完全一致,添加观察者、实现回调、发送完成后移除即可。

内容的提问来源于stack exchange,提问作者radar

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 11:46:06