在SwiftUI中,如何定义指向HStack或VStack构造函数的函数指针



我有这个视图,想简化它:

struct SUIBorderedIconTextButton: View {

struct IconInfo {
enum Position {
case left
case right
case top
case bottom

var isHorizontal: Bool {
return self == .left || self == .right
}

var isBeforeText: Bool {
return self == .left || self == .top
}
}

let icon: Image
let position: Position
}

let iconInfo: IconInfo?
let title: String
let fontSize: CGFloat
let backgroundColor: Color
let enabled: Bool
let action: () -> Void

@ViewBuilder
private var content: some View {
if let iconInfo = iconInfo {
switch iconInfo.position {
case .left:
HStack {
iconInfo.icon
Text(title).fontSize(fontSize)
}
case .right:
HStack {
Text(title).fontSize(fontSize)
iconInfo.icon
}
case .top:
VStack {
iconInfo.icon
Text(title).fontSize(fontSize)
}
case .bottom:
VStack {
Text(title).fontSize(fontSize)
iconInfo.icon
}
}
} else {
Text(title).fontSize(fontSize)
}
}

var body: some View {
Button(action: action) {
content
.padding()
.foregroundColor(color_button_text)
.background {
RoundedRectangle(cornerRadius: text_button_border_radius)
.foregroundColor(enabled ? backgroundColor : color_disabled_background)
}
}
.disabled(!enabled)
}
}

该视图只显示一个文本按钮,带有可选图标(位于文本的左/右/上/下(

如果位置是左或右,我们希望使用HStack。否则,请使用VStack。

若位置在顶部或左侧,我们希望将图标放在文本之前。否则,将图标放在文本后面。

请注意,在content构建器中有相当多的样板。

我为.top或.left案例创建了这个助手函数:


@ViewBuilder
private func group(iconInfo: IconInfo) -> some View {
if iconInfo.position.isBeforeText {
iconInfo.icon
Text(title).fontSize(fontSize)
} else {
Text(title).fontSize(fontSize)
iconInfo.icon
}
}

但我不知道如何选择构造函数。我可能需要一个指向init函数的指针,但我已经尝试过

let constructor = position.isHorizontal ? HStack.init : VStack.init
constructor {
... 
}

这显然不能编译。我不知道该怎么办。如果你有其他想法可以简化这个逻辑,也可以尝试一下。

三元运算符实际上不适用于SwiftUI类型,因为它们都是具有泛型的值类型,因此会导致构造不同的类型实体,并且不能分配给一个变量。

相反,你的案例可能的方法是类似

@ViewBuilder var content: some View {
Text("Text")
Image(systemName: "checkmark")
}
var body: some View {
if isHorizontal {
HStack{ content }
} else {
VStack{ content }
}
}

最新更新