如何在SwiftUI中访问子视图?

如何在SwiftUI中访问子视图?,swiftui,Swiftui,我正在开发SwiftUI,感觉它与React非常相似。刚才我正在自定义SwiftUI的一个按钮,但遇到了一个问题,即无法动态访问按钮的子视图 以下代码是我要做的: struct FullButton : View { var action: () -> Void var body: some View { Button(action: action) { // render children views here even what is that

我正在开发SwiftUI,感觉它与React非常相似。刚才我正在自定义SwiftUI的一个按钮,但遇到了一个问题,即无法动态访问按钮的子视图 以下代码是我要做的:

struct FullButton : View {
  var action: () -> Void
  var body: some View {
    Button(action: action) {
      // render children views here even what is that
      children
    }
  }
}
使用方法:

VStack {
  FullButton(action: {
    print('touched')
  }) {
    Text("Button")
  }
}
拜托,我有错误的想法吗


更新

取决于@graycampbell的回答,我试着如下

struct FullButton<Label> where Label : View {
    var action: () -> Void
    var label: () -> Label

    init(action: @escaping () -> Void, @ViewBuilder label: @escaping () -> Label) {
        self.action = action
        self.label = label
    }

    var body: some View {
        Button(action: action, label: label)
    }
}
错误是,
引用“VStack”上的初始值设定项“init(对齐:间距:内容:)”要求“FullButton”符合“View”

这意味着
FullButton
现在还没有返回
body

我不知道为什么会这样,因为
FullButton
仍然扩展
View
类。

请让我知道该类课程的正确定义。

如果我正确理解了你的问题,这就是你想要的:

struct FullButton:视图,其中Label:视图{
var操作:()->Void
变量标签:()->标签
var body:一些观点{
按钮(操作:self.action,标签:self.label)
}
}
这将允许您传递希望显示在按钮上的任何内容,这意味着您这里的代码现在可以工作了:

FullButton(操作:{
打印(“触摸”)
}) {
文本(“按钮”)
}
更新 在多次查看您的问题后,我意识到您的困惑源于对创建正常的
按钮时发生的事情的误解

在下面的代码中,我正在创建一个
按钮
。该按钮有两个参数-
action
label

按钮(操作:{},标签:{
文本(“按钮”)
})
如果我们查看
按钮
的文档,我们会发现其声明如下:

struct按钮,其中标签:视图
如果我们再看一下初始值设定项,我们会看到:

init(操作:@escaping()->Void,@ViewBuilder标签:()->label)
action
label
都需要闭包<代码>操作
需要返回类型为
无效
的闭包,
标签
需要返回类型为
标签
@ViewBuilder
闭包。正如
按钮声明中定义的那样,
标签是表示
视图的泛型,因此实际上,
标签
需要一个返回
视图
的闭包

这不是
按钮所独有的。以
HStack
为例:

struct HStack其中内容:查看
初始(对齐:垂直对齐=.center,间距:Length?=nil,@ViewBuilder content:()->content)
内容
按钮中的
标签
的作用相同

还有一点需要注意-当我们创建这样一个按钮时

按钮(操作:{}){
文本(“按钮”)
}
…我们实际上正在做与此相同的事情:

按钮(操作:{},标签:{
文本(“按钮”)
})
在Swift中,当方法调用中的最后一个参数是闭包时,我们可以省略参数标签并将闭包附加到右括号的外侧

在SwiftUI中,不能将内容隐式传递给任何
视图
视图必须在其初始值设定项中明确接受
@ViewBuilder
闭包。

因此,您不能将
@ViewBuilder
闭包传递给
FullButton
,除非
FullButton
接受
@ViewBuilder
闭包作为其初始值设定项中的参数,如我的答案开头所示。

有一个库使用Swift的反射从任何层次结构中提取SwiftUI视图

let view = FullButton()
let button = try view.inspect().button()
let children = button.anyView().view(OtherView.Type)
// By the way, you can even tap the button programmatically:
try button.tap()

您不“访问子对象”,而是根据一些
@State
变量声明要呈现的子对象,按钮的处理程序只会更新这些状态变量。你可能想用一些实际的例子来编辑你的问题,比如你希望点击按钮触发什么样的UI更改。你知道怎么做了吗?有可能“扩散”吗所有现有的
Button
初始值设定项参数以及直接从
FullButton
包装器中获取的修饰符,而不必一个接一个地复制它们并按此处所示向下传递?由于SwiftUI对视图使用
struct
而不是
class
,因此不能对
Button
进行子类化<代码>按钮
也不是
协议
,即使是,我想您仍然需要添加属性声明。您可以通过
FullButton
的初始值设定项传递
按钮,但我觉得这开始询问您为什么要从
FullButton
开始包装
按钮,以及是否有更好的方法来实现您的目标。我试着集中精力回答海报的原始问题,而不是反对他们在做什么,因为我不知道他们的理由。谢谢-我感谢你的意见。在React中,有一种相当常见的模式,即获取组件并对其应用一个或两个新属性(例如,行为或视觉样式)但是,将所有其他内容直接传递给SwiftUI,但在SwiftUI中,似乎最好使用导入和应用的自定义修改器或闭包之类的替代方法,而不必将视图包装到新视图中。@graycampbell,谢谢您的回答,但我仍然没有解决我的问题,你能检查一下我的问题更新吗?这对生产安全吗?@ Okkhanikhanhanv,这取决于你认为危险的地方。苹果评论拒绝?这里没有风险,库没有使用私有API。应用程序的整体稳定性?也许,这取决于你如何使用它。如果你使用它的方式,它的建设,这是为单位te
let view = FullButton()
let button = try view.inspect().button()
let children = button.anyView().view(OtherView.Type)
// By the way, you can even tap the button programmatically:
try button.tap()