SwiftUI应用通过Instruments leak检测后运行20分钟因内存问题崩溃排查
问题根源
Combine订阅无限堆积
你在ItemView的body中使用了.onReceive(Just(stringValue))做输入过滤,Just是每次视图重绘时都会重新生成的临时Publisher,SwiftUI的onReceive会为每一个新传入的Publisher创建独立订阅,且旧订阅不会自动释放。你每0.2秒更新一次laserPower会触发ItemView重绘一次,每次重绘都会新增订阅,运行20分钟会积累数万无效订阅,内存持续上涨直到触发系统终止。
这个问题不会被Leak检测工具识别,因为这些订阅仍然被视图持有,属于存活对象的无限制增长,不属于无主泄漏对象。正则实例重复创建无缓存
你封装的String.contain(pattern:)方法每次调用都会重新生成NSRegularExpression实例,每次数值更新时会多次调用该方法做正则匹配,大量重复的正则实例会额外占用内存,加快内存上涨速度。定时器无生命周期管理
ContentView中创建的重复Timer没有存储为可取消实例,也没有在页面销毁时主动取消,只要应用在前台就会持续触发数值更新,持续产生新的视图重绘和内存占用。
修复方案
- 移除
onReceive(Just)逻辑:将stringValue的输入过滤逻辑放到自定义Binding中实现,完全不需要Combine订阅,从根源避免订阅堆积 - 新增正则缓存:把用到的正则表达式提前创建为静态常量存储,每次匹配直接复用,避免重复创建实例
- 管理定时器生命周期:将Timer的
Cancellable存储到@State变量中,页面onDisappear时主动取消定时器 - 优化冗余代码:可移除不必要的
DispatchQueue.main.async包裹,避免多余的队列任务堆积占用内存
内容的提问来源于stack exchange,提问作者Manh Khuc
相关产品推荐
相关产品推荐

