非ARC环境下NSTextView手动释放未触发dealloc的问题排查
非ARC下NSTextView需两次release才触发dealloc的原因
核心原因:双重引用计数叠加
你遇到的情况是两种引用计数增加行为叠加导致的:
属性的retain语义:如果你的
textView属性声明为@property (retain) MyCustomTextView *textView;(这是非ARC下Cocoa控件属性的常规写法),赋值时会自动对实例执行一次retain操作:[[MyCustomTextView alloc] init]会让引用计数变为1- 赋值给
self.textView时,retain属性会将计数再加1,变为2 - 调用1次
release后计数降到1,未达到0,所以不会触发dealloc;第二次调用release计数归0,才会触发对象销毁
NSTextView内部的隐式retain:部分Cocoa控件(包括NSTextView)在初始化过程中,框架会自动对实例增加一次引用计数。比如NSTextView会创建
NSTextStorage、NSLayoutManager等内部关联对象,这些对象会持有NSTextView的引用,用来维持文本渲染、编辑逻辑的正常运行,这会额外让计数+1。即使你的属性是assign语义,也可能出现需要两次release才能销毁的情况。
解决建议(适配窗口销毁重建场景)
规范属性与内存管理:如果使用
retain属性,建议初始化时给实例加上autorelease:@autoreleasepool { self.textView = [[[MyCustomTextView alloc] init] autorelease]; }这样后续只需要在窗口销毁时,对
self.textView执行一次release,或者直接将self.textView置为nil(retain属性置nil会自动释放旧值)。窗口销毁时的清理逻辑:在窗口销毁的回调方法中,先断开所有关联(比如移除通知监听、清空委托),再执行:
[self.textView release]; self.textView = nil;确保引用计数能正确归0,避免内存泄漏。
内容的提问来源于stack exchange,提问作者Charlie
相关产品推荐
相关产品推荐

