将视图作为参数添加到自定义 ViewModifier

Sla*_*ppy 5 ios swift swiftui

这更多的是一个语法问题。我试图在不使用 AnyView 的情况下将视图传递到 ViewModifier 初始化程序中。

目前我有一些使用 AnyView 运行的东西,但我想使用通用视图语法,就像您将“某些视图”传递到此答案中概述的视图一样:

如何将一个 SwiftUI View 作为变量传递给另一个 View 结构

我似乎无法让它与 ViewModifier 一起使用。

其目的(如示例中所示)是让修饰符将计算值传递到 innerView 中。我也很高兴使用@ViewBuilder以某种方式指定innerView属性,因为这可能会产生相同的效果。

这是示例修改器:

struct SampleModifier: ViewModifier {

    let param1: CGFloat
    let innerView:  (CGFloat, CGFloat) -> AnyView
    
    // Assume these are calculated states
    let calculatedParam1: CGFloat = 100
    let calculatedParam2: CGFloat = 100
    
    func body(content: Content) -> some View {
        ZStack {
            HStack {
                Spacer()

                innerView(self.calculatedParam1, self.calculatedParam2)
                    .padding(.leading, 10)
                    .frame(width: param1)
            }
            
            content.frame(width: 100, height: 100)
        }
        
    }
}
Run Code Online (Sandbox Code Playgroud)

及其用途:

struct SampleView: View {
    var body: some View {
        Rectangle()
            .modifier(SampleModifier(param1: 150, innerView: { param1, param2 in
                return AnyView(
                    Text("Inner View: \(param1) - \(param2)")
                )
            }))
    }
}
Run Code Online (Sandbox Code Playgroud)

paw*_*222 7

您可以使用泛型,即 makeinnerView返回一些视图:

struct SampleModifier<V>: ViewModifier where V: View {
    let param1: CGFloat
    let innerView: (CGFloat, CGFloat) -> V

    ...
}
Run Code Online (Sandbox Code Playgroud)

那么你就不再需要AnyView

struct SampleView: View {
    var body: some View {
        Rectangle()
            .modifier(SampleModifier(param1: 150, innerView: { param1, param2 in
                Text("Inner View: \(param1) - \(param2)")
            }))
    }
}
Run Code Online (Sandbox Code Playgroud)

或者,您可以创建一个View扩展:

extension View {
    func sampleModifier<V>(
        param1: CGFloat,
        innerView: @escaping (CGFloat, CGFloat) -> V
    ) -> some View where V: View {
        modifier(SampleModifier(param1: param1, innerView: innerView))
    }
}
Run Code Online (Sandbox Code Playgroud)

并像这样使用它:

struct SampleView: View {
    var body: some View {
        Rectangle()
            .sampleModifier(param1: 150, innerView: { param1, param2 in
                Text("Inner View: \(param1) - \(param2)")
            })
    }
}
Run Code Online (Sandbox Code Playgroud)

  • @Slappy我用视图扩展更新了我的答案。 (2认同)