传入逃逸闭包的函数是否会对所属实例产生强引用?
Swift逃逸闭包传递实例方法导致的内存泄漏问题
核心结论
直接传递实例方法给逃逸闭包(如functionWithEscapingClosure(closure: functionGivenToTheClosure(_:)))会隐式强捕获当前实例,这大概率是你的ViewController无法释放的原因。
原因解释
Swift中,当你把实例方法作为闭包参数传递时,编译器会自动生成一个闭包,这个闭包会强引用实例本身——哪怕你的方法内部没有显式使用self。因为实例方法必须依附于实例才能执行,所以这个隐式的强引用是默认行为。如果目标闭包是@escaping类型,这个强引用会被外部持有,导致ViewController的引用计数无法归零,最终引发内存泄漏。
解决方法
方法1:显式使用弱引用捕获列表
把直接传方法的写法改成带捕获列表的闭包形式,明确指定弱引用self:
functionWithEscapingClosure { [weak self] parameter in self?.functionGivenToTheClosure(parameter) }
这样闭包只会持有self的弱引用,当ViewController被销毁时,引用链会被打断,不会阻碍内存释放。
方法2:将方法改为静态方法(如果适用)
如果functionGivenToTheClosure(_:)不需要访问任何实例属性或方法,可以把它声明为静态方法:
static func functionGivenToTheClosure(_ parameter: ParameterType) { // 方法实现 }
此时传递Self.functionGivenToTheClosure(_:)就不会捕获任何实例引用,自然不会造成内存泄漏。
验证方式
使用Xcode的Memory Graph Debugger(点击调试栏中的内存图标),查看ViewController的引用链,确认是否存在来自目标逃逸闭包的强引用,以此验证问题根源。
内容的提问来源于stack exchange,提问作者Ömer Faruk Gökce
相关产品推荐
相关产品推荐

