iosswiftstructclosuresswiftui

How to implement function like onAppear in SwiftUI?


So, I would like to create a custom view and add function. How can I implement a function like .onAppear(perform: (() -> Void)?)? My code does not work, onDismiss closure does not call in the 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")
       })
      )
    }
  }
}

Solution

  • Here is possible approach. Tested & worked with 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")
           })
          )
        }
      }
    }
    

    Update: possible alternate for usage with modifier:

        ...
        .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")
           })
          )
        }
      }
    }