如何访问SwiftUI中的子视图?

如何访问SwiftUI中的子视图?,swift,swiftui,Swift,Swiftui,我正在尝试我们的SwiftUI,并希望在SwiftUI的组件行上创建一个组件。 所以,我想做的是: 创建一个扩展视图的新视图 struct CustomComponent: View { var title: String var body: some View { HStack { Image(systemName: "") // This would be updated through style

我正在尝试我们的SwiftUI,并希望在SwiftUI的组件行上创建一个组件。 所以,我想做的是:

创建一个扩展视图的新视图

struct CustomComponent: View {
    var title: String
    var body: some View {
        HStack {
            Image(systemName: "") // This would be updated through style
            Text(verbatim: title)
        }

    }
}

extension View {

    public func componentStyle<S>(_ style: S) -> some View where S : ComponentStyle {
        guard self is CustomComponent else {
            return AnyView(self)
        }

        return AnyView(
// Here I want to add the spacing attribute of the style to the HStack.
// Also I want to update the Image with the corresponding style's icon.
// If it's not possible here, please suggest alternate place.
            self
                .foregroundColor(style.tintColor)
                .frame(height: style.height)
        )
    }

}

public protocol ComponentStyle {
    var icon: String { get }
    var tintColor: Color { get }
    var spacing: CGFloat { get }
    var height: CGFloat { get }
}

struct ErrorStyle: ComponentStyle {
    var icon: String {
        return "xmark.octagon"
    }

    var tintColor: Color {
        return .red
    }

    var spacing: CGFloat {
        return 8
    }

    var height: CGFloat {
        return 24
    }
}

struct CustomComponent:视图{
变量标题:字符串
var body:一些观点{
HStack{
Image(systemName:)//这将通过样式更新
文本(逐字:标题)
}
}
}
扩展视图{
public func componentStyle(style:S)->一些视图,其中S:componentStyle{
守卫自己是另一个{
返回任意视图(self)
}
返回任意视图(
//在这里,我想将样式的间距属性添加到HStack。
//我还想用相应样式的图标更新图像。
//如果这里不可能,请建议其他地方。
自己
.foregroundColor(style.tintColor)
.框架(高度:样式.高度)
)
}
}
公共协议组件样式{
变量图标:字符串{get}
var tintColor:Color{get}
变量间距:CGFloat{get}
变量高度:CGFloat{get}
}
结构错误样式:ComponentStyle{
变量图标:字符串{
返回“xmark.octagon”
}
颜色:颜色{
返回,红色
}
变量间距:CGFloat{
返回8
}
变量高度:CGFloat{
返回24
}
}
我如何实现以下目标:

  • 如何将样式的间距属性添加到HStack
  • 如何使用相应样式的图标更新图像

谢谢

您可以创建自定义的
环境密钥

extension EnvironmentValues {
    private struct ComponentStyleKey: EnvironmentKey {
        static let defaultValue: ComponentStyle = ErrorStyle()
    }
    
    var componentStyle: ComponentStyle {
        get { self[ComponentStyleKey] }
        set { self[ComponentStyleKey] = newValue }
    }
}
并使用它将一些
组件样式
作为
@环境
变量传递:

struct ContentView: View {
    var body: some View {
        CustomComponent(title: "title")
            .componentStyle(ErrorStyle())
    }
}

struct CustomComponent: View {
    @Environment(\.componentStyle) private var style: ComponentStyle
    var title: String

    var body: some View {
        HStack(spacing: style.spacing) {
            Image(systemName: style.icon)
            Text(verbatim: title)
        }
    }
}

extension CustomComponent {
    func componentStyle<S>(_ style: S) -> some View where S: ComponentStyle {
        environment(\.componentStyle, style)
    }
}
struct ContentView:View{
var body:一些观点{
自定义组件(标题:“标题”)
.componentStyle(ErrorStyle())
}
}
结构自定义组件:视图{
@环境(\.componentStyle)私有变量样式:componentStyle
变量标题:字符串
var body:一些观点{
HStack(间距:样式.间距){
图像(系统名称:style.icon)
文本(逐字:标题)
}
}
}
扩展自定义组件{
func componentStyle(style:S)->一些视图,其中S:componentStyle{
环境(\.componentStyle,style)
}
}

我的主要要求是创建一个类似于
labelStyle(labelStyle)
等的函数,以便保持类似于SwiftUI的格式。感谢上面的方法,但这正是我现在使用的方法。@schinj我用
componentStyle
的方法更新了我的答案-如果需要,您可以调整它,使其具有
labelStyle(labelStyle())
。我想这就是我所需要的。最后一个问题,您是否意识到大量使用环境对象有任何副作用(内存、性能)?@schinj我不知道。但是环境变量通常比环境对象轻。很抱歉混淆了。但我说的是环境变量。他们是否存在记忆或性能风险?