如何在SwiftUI中实现onAppear这样的功能?

问题描述 投票:0回答:2

所以,我想创建一个自定义视图并添加功能。如何实现像

.onAppear(perform: (() -> Void)?)
这样的功能?我的代码不起作用,
onDismiss
闭包不会在
DashboardView
中调用。

struct DashboardView: View {

  @State var employees = ["Alex", "Olga", "Mark"]
  @State var presentEmployeeView = false

  var body: some View {
    NavigationView {
      List {
        Section {
          Button(action: {
            self.presentEmployeeView = true
          }, label: {
            Text("All employees")
          }).buttonStyle(BorderlessButtonStyle())
        }
      }
    }
    .sheet(isPresented: $presentEmployeeView) {
      EmployeesView(employees: self.employees).onDismiss {
        self.presentEmployeeView = false
      }
    }
  }
}

struct EmployeesView: View {
  let employees: [String]

  @State private var onDismissClosure: (() -> Void)? = nil
  func onDismiss(perform action: (() -> Void)? = nil) -> some View {
    self.onDismissClosure = action
    return self
  }

  var body: some View {
    NavigationView {
      List {
        ForEach(employees) { employee in
          EmployeeCell(employee: employee)
        }
      }.navigationBarItems(leading:
        Button(action: {
          self.onDismissClosure?()
        }, label: {
          Text("Close")
       })
      )
    }
  }
}
ios swift struct closures swiftui
2个回答
1
投票

这是可能的方法。已测试并使用 Xcode 11.4 / iOS 13.4

struct DashboardView: View {

  @State var employees = ["Alex", "Olga", "Mark"]
  @State var presentEmployeeView = false

  var body: some View {
    NavigationView {
      List {
        Section {
          Button(action: {
            self.presentEmployeeView = true
          }, label: {
            Text("All employees")
          }).buttonStyle(BorderlessButtonStyle())
        }
      }
    }
    .sheet(isPresented: $presentEmployeeView) {
      EmployeesView(employees: self.employees) {
        self.presentEmployeeView = false
      }
    }
  }
}

struct EmployeesView: View {
  let employees: [String]
  var onDismiss = {}

  var body: some View {
    NavigationView {
      List {
        ForEach(employees, id: \.self) { employee in
          Text("\(employee)")
        }
      }.navigationBarItems(leading:
        Button(action: {
          self.onDismiss()
        }, label: {
          Text("Close")
       })
      )
    }
  }
}

更新:可能与修饰符一起使用的替代方案:

    ...
    .sheet(isPresented: $presentEmployeeView) {
      EmployeesView(employees: self.employees).onDismiss {
        self.presentEmployeeView = false
      }
    }
  }
}

struct EmployeesView: View {
  let employees: [String]
  var onDismiss = {}

  func onDismiss(_ callback: @escaping () -> ()) -> some View {
    EmployeesView(employees: employees, onDismiss: callback)
  }

  var body: some View {
    NavigationView {
      List {
        ForEach(employees, id: \.self) { employee in
          Text("\(employee)")
        }
      }.navigationBarItems(leading:
        Button(action: {
          self.onDismiss()
        }, label: {
          Text("Close")
       })
      )
    }
  }
}

0
投票

您可以通过使用以下组合来实现此目的,而无需构造函数包装器:

  1. @环境
  2. 视图修改器
    // define a custom type of environment key for closures
    private struct ClosureKey: EnvironmentKey {
        static let defaultValue: (() -> Void)? = {}
    }

    // define a new environment property
    extension EnvironmentValues {
        var myAction: (() -> Void)? {
            get { self[ClosureKey.self]}
            set { self[ClosureKey.self] = newValue }
        }
    }

    struct MyActionModifier: ViewModifier {
        var perform: (() -> Void)?

        func body(content: Content) -> some View {
            content.environment(\.myAction, perform)
        }
    }

    struct ChildView: View {
        @Environment(\.myAction) var action: (() -> Void)?
        
        var body: some View {
            Button(action: {
                self.action?()
            })
        }

        func myAction(_ perform: (() -> Void)?) { 
           self.modifier(MyActionModifier(perform: perform) 
        }
    }

回报:

    struct ParentView: View {
        var body: some View {
            ChildView()
                .myAction({print("hello world")})
        }
    }

实际上这纯粹是疯狂。我认为在构造函数中使用可选的闭包是非常可取的。但也许这个过程可以简化。毕竟,声明

ClosureKey
只需要做一次。也许 MyActionModifier 可以重构为使用动态 KeyPath?这将使环境值扩展成为每个自定义环境值的主要任务。

但是,我什至还不能 100% 确定这是否有效。

来源:

  1. https://useyourloaf.com/blog/swiftui-custom-environment-values/
  2. 用于自定义视图的 SwiftUI ViewModifier
  3. SwiftUI:环境中商店关闭?
© www.soinside.com 2019 - 2024. All rights reserved.