使用 UIViewControllerRepresentable 时 SwiftUI 内存泄漏
SwiftUI memory leak when using UIViewControllerRepresentable
更新:从 beta4 开始,问题仍然存在。
我创建了一个非常简单的示例,说明 UIViewControllerRepresentable 表示的 UIViewController 如何从不 释放。
import SwiftUI
struct ContentView : View {
@State private var showRepView = true
var body: some View {
VStack {
Text("Square").font(.largeTitle).tapAction {
self.showRepView.toggle()
}
if showRepView {
SomeRepView().frame(width: 100, height: 100)
}
}
}
}
表示实现如下:
import SwiftUI
struct SomeRepView: View {
var body: some View {
RepViewController()
}
}
struct RepViewController: UIViewControllerRepresentable
{
func makeUIViewController(context: Context) -> SomeCustomeUIViewController {
let vc = SomeCustomeUIViewController()
print("INIT \(vc)")
return vc
}
func updateUIViewController(_ uiViewController: SomeCustomeUIViewController, context: Context) {
}
static func dismantleUIViewController(_ uiViewController: SomeCustomeUIViewController, coordinator: Self.Coordinator) {
print("DISMANTLE")
}
}
class SomeCustomeUIViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = UIColor.green
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
print("viewWillDissapear \(self)")
}
deinit {
print("DEINIT \(self)")
}
}
通过点击 "Square" 按钮,可以交替添加和删除 SomeRepView
。但是,相关的 UIViewController 从未发布。这可以从记录的消息中看出,我也通过 Instruments 进行了确认。
请注意,SomeRepView 已正确释放。只有相应的视图控制器保留分配。
另请注意 UIViewController.viewWillDissappear
和 UIViewControllerRepresentable.dismantleUIViewController
被调用
这是重复按方形按钮的典型输出。
INIT <SomeCustomeUIViewController: 0x100b1af70>
DISMANTLE
viewWillDissapear <SomeCustomeUIViewController: 0x100b1af70>
INIT <SomeCustomeUIViewController: 0x100a0a8c0>
DISMANTLE
viewWillDissapear <SomeCustomeUIViewController: 0x100a0a8c0>
INIT <SomeCustomeUIViewController: 0x100b23690>
DISMANTLE
viewWillDissapear <SomeCustomeUIViewController: 0x100b23690>
如图所示,DEINIT
从未被打印出来。
我的问题是...这是一个错误吗?还是我做错了什么?
运行iOS13,测试版 4。
我尝试触发模拟内存警告。没有效果。控制器坚持。仪器是我的见证;-)
在 Xcode 11,beta 5 中,修复了错误。
更新:从 beta4 开始,问题仍然存在。
我创建了一个非常简单的示例,说明 UIViewControllerRepresentable 表示的 UIViewController 如何从不 释放。
import SwiftUI
struct ContentView : View {
@State private var showRepView = true
var body: some View {
VStack {
Text("Square").font(.largeTitle).tapAction {
self.showRepView.toggle()
}
if showRepView {
SomeRepView().frame(width: 100, height: 100)
}
}
}
}
表示实现如下:
import SwiftUI
struct SomeRepView: View {
var body: some View {
RepViewController()
}
}
struct RepViewController: UIViewControllerRepresentable
{
func makeUIViewController(context: Context) -> SomeCustomeUIViewController {
let vc = SomeCustomeUIViewController()
print("INIT \(vc)")
return vc
}
func updateUIViewController(_ uiViewController: SomeCustomeUIViewController, context: Context) {
}
static func dismantleUIViewController(_ uiViewController: SomeCustomeUIViewController, coordinator: Self.Coordinator) {
print("DISMANTLE")
}
}
class SomeCustomeUIViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = UIColor.green
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
print("viewWillDissapear \(self)")
}
deinit {
print("DEINIT \(self)")
}
}
通过点击 "Square" 按钮,可以交替添加和删除 SomeRepView
。但是,相关的 UIViewController 从未发布。这可以从记录的消息中看出,我也通过 Instruments 进行了确认。
请注意,SomeRepView 已正确释放。只有相应的视图控制器保留分配。
另请注意 UIViewController.viewWillDissappear
和 UIViewControllerRepresentable.dismantleUIViewController
这是重复按方形按钮的典型输出。
INIT <SomeCustomeUIViewController: 0x100b1af70>
DISMANTLE
viewWillDissapear <SomeCustomeUIViewController: 0x100b1af70>
INIT <SomeCustomeUIViewController: 0x100a0a8c0>
DISMANTLE
viewWillDissapear <SomeCustomeUIViewController: 0x100a0a8c0>
INIT <SomeCustomeUIViewController: 0x100b23690>
DISMANTLE
viewWillDissapear <SomeCustomeUIViewController: 0x100b23690>
如图所示,DEINIT
从未被打印出来。
我的问题是...这是一个错误吗?还是我做错了什么?
运行iOS13,测试版 4。
我尝试触发模拟内存警告。没有效果。控制器坚持。仪器是我的见证;-)
在 Xcode 11,beta 5 中,修复了错误。