SwiftUI:视图完全移除时的ViewModifier回调,类似于onDisappear,但只调用一次

g52tjvyc  于 2024-01-05  发布在  Swift
关注(0)|答案(1)|浏览(140)

当视图是层次结构的一部分时,onAppearonDisappear修饰符可以被多次调用。
我知道有一个技巧,使一个onLoad ViewModifier像这样

  1. extension View {
  2. func onLoad(perform action: (() -> Void)? = nil) -> some View {
  3. self.modifier(ViewDidLoadModifier(action: action))
  4. }
  5. }
  6. struct ViewDidLoadModifier: ViewModifier {
  7. @State private var viewDidLoad = false
  8. let action: (() -> Void)?
  9. func body(content: Content) -> some View {
  10. content
  11. .onAppear {
  12. if viewDidLoad == false {
  13. viewDidLoad = true
  14. action?()
  15. }
  16. }
  17. }
  18. }

字符串
从上面的代码中,onLoad只会被调用一次

  1. struct MyView: View {
  2. var body: some View {
  3. Text("Hello View")
  4. .onAppear {
  5. // may print multiple times
  6. print("onAppear")
  7. }
  8. .onLoad {
  9. // only prints once
  10. // when the view first appears in the hierarchy
  11. print("onLoad")
  12. }
  13. }
  14. }


有没有一种方法可以有一个onUnLoad ViewModifier?

  1. struct MyView: View {
  2. var body: some View {
  3. Text("Hello View")
  4. .onDisappear {
  5. // may print multiple times
  6. print("onDisappear")
  7. }
  8. .onUnLoad {
  9. // only prints once,
  10. // when the view is completely removed
  11. print("onUnLoad")
  12. }
  13. }
  14. }

iklwldmw

iklwldmw1#

我找到了一种方法来创建onUnload ViewModifier,将UIView Package 在UIViewRepresentable中,并使用其willMove(toSuperview:)事件

  1. struct ViewDidUnloadModifier: ViewModifier {
  2. let action: () -> Void
  3. func body(content: Content) -> some View {
  4. ZStack {
  5. ViewDidUnloadRepresentable(action: action)
  6. content
  7. }
  8. }
  9. }
  10. struct ViewDidUnloadRepresentable: UIViewRepresentable {
  11. let action: () -> Void
  12. func makeUIView(context: Context) -> DidUnloadView {
  13. return DidUnloadView(action: action)
  14. }
  15. func updateUIView(_ uiView: DidUnloadView, context: Context) {
  16. }
  17. }
  18. final class DidUnloadView: UIView {
  19. let action: () -> Void
  20. init(action: @escaping () -> Void) {
  21. self.action = action
  22. super.init(frame: .zero)
  23. }
  24. required init?(coder: NSCoder) {
  25. fatalError("init(coder:) has not been implemented")
  26. }
  27. override func willMove(toSuperview newSuperview: UIView?) {
  28. if newSuperview == nil {
  29. action()
  30. }
  31. super.willMove(toSuperview: newSuperview)
  32. }
  33. }

字符串
在UIKit中,如果调用了视图的willMove(toSuperview:)方法,并且toSuperview为nil,则意味着将从层次结构中完全删除UIView。

  1. struct MyView: View {
  2. var body: some View {
  3. Text("Hello View")
  4. .onDisappear {
  5. // may print multiple times
  6. print("onDisappear")
  7. }
  8. .onUnload {
  9. // only prints once when removed, EUREKA!
  10. print("onUnload")
  11. }
  12. }
  13. }

展开查看全部

相关问题