SwiftUI持有是一种常见的View (struct)做法ObservableObject。由于 astruct不是引用类型,因此很容易忘记 is 保存着一个。
两者的答案都是肯定的。
class ViewModel: ObservableObject
...
struct MyView: View {
@ObservedObject var viewModel: ViewModel
var body: some View {
Button("Action") {
viewModel?.handler {
// ViewModel is retained here through self:
// (MyView.viewModel)
self.someAction()
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
在 中SwiftUI,将自己“传递给”你的人并不是一个好习惯。ViewModel
class A {
var next: A
}
let a = A()
a.next = a // Retain cycle of an object to itself.
Run Code Online (Sandbox Code Playgroud)
(原问题)
为什么即使闭包不保留任何内容,持有对闭包的引用也会导致内存泄漏?
(这始于一个SwiftUI问题,但我不确定它是否真的相关)
所以这里有一个简单的 Manager ( ViewModel),它包含一个闭包。
class Manager: ObservableObject {
private var handler: (() -> Void)?
deinit {
print("Manager deallocated")
}
func shouldDismiss(completion: @escaping () -> Void) {
handler = completion
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
self.handler?()
}
}
}
Run Code Online (Sandbox Code Playgroud)
这是一个视图,使用它:
struct LeakingView: View {
@ObservedObject var manager: Manager
let shouldDismiss: () -> Void
var body: some View {
Button("Dismiss") { [weak manager] in
manager?.shouldDismiss {
self.shouldDismiss()
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
这是ViewController激活流程:
class ViewController: UIViewController {
var popup: UIViewController?
@IBAction func openViewAction(_ sender: UIButton) {
let manager = Manager()
let suiView = LeakingView(manager: manager) { [weak self] in
self?.popup?.view.removeFromSuperview()
self?.popup?.dismiss(animated: true)
self?.popup = nil
}
popup = LKHostingView(rootView: suiView)
popup?.view.frame.size = CGSize(width: 300, height: 300)
view.addSubview(popup!.view)
}
}
Run Code Online (Sandbox Code Playgroud)
当运行这个时,只要管理器持有闭包,它就会泄漏并且Manager不会被释放。
保留周期在哪里?
为什么即使闭包不保留任何内容,持有对闭包的引用也会导致内存泄漏?
因为闭包确实保留了一些东西。它保留了self.
例如,当你说
manager?.shouldDismiss {
shouldDismiss()
}
Run Code Online (Sandbox Code Playgroud)
第二个shouldDismiss意思self.shouldDismiss是并保留self。因此,LeakingView 保留了 Manager,但 Manager 通过闭包现在保留了 LeakingView。保留循环!
这就是为什么人们[weak self] in一开始就说这样的关闭。
| 归档时间: |
|
| 查看次数: |
487 次 |
| 最近记录: |