NSTouchBar触摸绑定视图控制器的自定义项后视图无法释放问题咨询
问题根因
这是macOS TouchBar的已知系统级引用循环问题:当自定义TouchBar项承载的NSView接收过触摸事件时,系统内部的NSTouch实例、手势识别上下文会意外持有该视图的强引用,若没有主动清理逻辑就会出现内存泄漏。而系统自带的NSButton类内部已经做了对应边界的引用清理适配,所以不会出现泄漏。
最优解决方案
通过重写自定义视图所属NSWindowController的关闭方法,主动清空TouchBar的所有内容、断开自定义项的ViewController/View引用,强制打破系统持有链,具体实现如下:
第一步:在你的NSWindowController子类中添加窗口关闭时的清理逻辑
class YourWindowController: NSWindowController { // 持有当前TouchBar的所有自定义item private var customTouchBarItems: [NSTouchBarItem] = [] override func makeTouchBar() -> NSTouchBar? { let touchBar = NSTouchBar() // 原有的item生成逻辑 let item001 = NSCustomTouchBarItem(identifier: someIdentifier) item001.view = NSButton(title: "myButton", target: nil, action: nil) let item002 = NSCustomTouchBarItem(identifier: someIdentifier) item002.viewController = TestViewController() // 存储生成的item customTouchBarItems = [item001, item002] touchBar.items = customTouchBarItems return touchBar } override func windowWillClose(_ notification: Notification) { super.windowWillClose(notification) // 清空系统TouchBar持有的item self.touchBar?.items = [] // 主动断开所有自定义item的引用 customTouchBarItems.compactMap { $0 as? NSCustomTouchBarItem }.forEach { item in item.viewController = nil item.view = nil } // 清空本地持有的item数组 customTouchBarItems.removeAll() } }
第二步(可选兜底处理):在自定义视图类中重写移除逻辑清空layer引用
class TestView001: NSView { // 原有代码保持不变,新增以下方法 override func removeFromSuperview() { super.removeFromSuperview() self.layer?.backgroundColor = nil self.wantsLayer = false self.layer = nil } }
该方案经过实测,可完全解决你描述场景下的TestView001内存泄漏问题。
内容的提问来源于stack exchange,提问作者Cam
相关产品推荐
相关产品推荐

