排查SwiftUI macOS应用中Apple核心框架相关内存泄漏
SwiftUI macOS应用内存持续增长排查困境
问题概述
- 开发的SwiftUI macOS应用存在内存持续增长问题,运行数小时后会彻底卡顿。
- 已尝试使用Xcode Memory Graph和Instruments工具排查内存泄漏,但示例中的问题都较为明显,自身问题难以定位。
- 运行Instruments后发现泄漏对象并不固定:

- Xcode Memory Graph显示泄漏源头是CoreFoundation下的NSSet,无法定位到自身代码,作为新手陷入困境。
补充调查进展
初步怀疑
怀疑问题与AVPlayer组件相关,后续调查进一步验证了这一方向。
关键发现
启动AVPlayer播放后内存会无限制增长,标注后的内存分析图如下:
AVPlayer相关代码实现
struct VideoPlayerView: NSViewRepresentable { @Environment(GlobalTimelineModel.self) var globalTimelineModel var playerView: AVPlayerView var player: AVPlayer @Binding var currentPlayerTime: CMTime @Binding var isPlaying: Bool @Binding var loopStart: Double @Binding var loopEnd: Double @Binding var shouldLoop: Bool @Binding var isScrubbing: Bool @State var shouldResumePlayback: Bool = false /// 拖动进度条暂停播放时设为true func makeCoordinator() -> Coordinator { Coordinator(self) } func makeNSView(context: Context) -> AVPlayerView { playerView.player = player playerView.controlsStyle = .none playerView.player?.replaceCurrentItem(with: globalTimelineModel.videoAVPlayerItem) playerView.player?.isMuted = true context.coordinator.onTimeUpdate = { time in currentPlayerTime = time } return playerView } func updateNSView(_ nsView: AVPlayerView, context: Context) { if nsView.player != player{ nsView.player = player } if isPlaying{ player.playImmediately(atRate: 1.0) // 播放到结尾时从头开始 if let playerCurrentTime = nsView.player?.currentTime().seconds, let playerDuration = nsView.player?.currentItem?.duration.seconds{ if playerCurrentTime >= playerDuration{ player.seek(to: .zero, toleranceBefore: .zero, toleranceAfter: .zero) } } } else{ if player.rate != 0{ player.pause() } } } func updatePlaybackPosition(player: AVPlayer){ player.seek(to: currentPlayerTime, toleranceBefore: .zero, toleranceAfter: .zero) } func isWithinThreshold(value1: Double, value2: Double, threshold: Double) -> Bool { return abs(value1 - value2) <= threshold } class Coordinator { private var timeObserverToken: Any? private weak var player: AVPlayer? // 使用弱引用持有player var onTimeUpdate: ((CMTime) -> Void)? init(_ parent: VideoPlayerView) { print("Coordinator初始化") self.player = parent.player // 存储player的弱引用 addPeriodicTimeObserver() } private func addPeriodicTimeObserver() { guard let player = player else { return } let interval = CMTime(value: 1, timescale: 24) timeObserverToken = player.addPeriodicTimeObserver(forInterval: interval, queue: .main) { [weak self] time in guard let self = self else { return } self.onTimeUpdate?(time) } } private func removePeriodicTimeObserver() { guard let timeObserverToken = timeObserverToken, let player = player else { return } player.removeTimeObserver(timeObserverToken) self.timeObserverToken = nil } deinit { print("Coordinator销毁") removePeriodicTimeObserver() } } }
内存分析细节图

内容的提问来源于stack exchange,提问作者user1542125
相关产品推荐
相关产品推荐

