所以,我想创建一个自定义视图并添加功能。如何实现像
.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")
})
)
}
}
}
这是可能的方法。已测试并使用 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")
})
)
}
}
}
您可以通过使用以下组合来实现此目的,而无需构造函数包装器:
// 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% 确定这是否有效。
来源: