如何从结构视图数组中提取状态?SwiftUI



从SwiftUI结构数组中获取状态时遇到问题。

我有一个包含topText和bottomText的卡片结构。我有另一个结构,它是用于输入组件(如卡片(的窗体。我将这些卡片存储在一个数组中,当点击+按钮时,会添加越来越多的卡片。在父视图中,我在该数组上有一个foreach,以便它们动态渲染。

我在试图从这些结构中提取状态值时遇到了问题。卡片包含顶部文本和底部文本的状态。当在父数组(卡数组所在的位置(中单击保存按钮时,它会遍历卡数组,并通过get方法打印它们的状态。然而,它并没有打印这些卡片的当前状态。它打印一个空白字符串。我相信这是因为当我附加结构时,它只是复制一个死结构,而不是真正的有状态结构。

我的假设正确吗?或者这是swiftUI中的一个错误?有人对正确的方法有什么想法吗?每当点击按钮时,我只想从卡片中获得输入。不过,它需要是动态的,因为用户可以随意多次点击+按钮,并继续制作更多的卡片。

这是卡片粘贴的代码:

struct memeCard: View, Identifiable{
@State private var topText = ""
@State private var bottomText = ""
let id = UUID()
//  TODO: figure out how to make text wrap so it doesn't go on one line forever.
var body: some View{
VStack(spacing: 30){
TextField("Top text...", text: $topText).multilineTextAlignment(.center)
Divider()
TextField("Bottom text...", text: $bottomText)
}
.frame(width: 300, height: 350, alignment: .center).multilineTextAlignment(.center)
.background(Color.white)
.cornerRadius(20)
.shadow(color: Color.gray, radius: 4, x: 4, y: 4)
}
func getBottomText() -> String{
return self.bottomText
}
func getTopText() -> String{
return self.topText
}
}

这是父视图:


struct CreateMemePage: View {
@Environment(.presentationMode) var presentation
let realm = try! Realm()
@State private var sectionInput = ""
@State private var memeTitleInput = ""
@State private var offsetValue: CGFloat = 0.0
@State private var createCards: [memeCard] = [memeCard()]
var body: some View {
NavigationView{
VStack(spacing: 30){
ScrollView{
TextField("Section...", text: $sectionInput)
.multilineTextAlignment(.center)
.frame(width: 350, height: 75, alignment: .center)
.background(Color.white)
.cornerRadius(15)
.shadow(color: Color.gray, radius: 4, x: 4, y: 4)
TextField("Meme Title...", text: $memeTitleInput)
.multilineTextAlignment(.center)
.frame(width: 350, height: 75, alignment: .center)
.background(Color.white)
.cornerRadius(15)
.shadow(color: Color.gray, radius: 4, x: 4, y: 4)

ForEach(0..<self.createCards.count, id: .self){ item in
self.createCards[item].padding()
}
.frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: .infinity, alignment: .center)
}
Button(action: {
self.createCards.append(memeCard())
}) {
Image(systemName: "plus")
.accentColor(Color.white)
.frame(width: 50, height: 50, alignment: .center)
.background(LinearGradient(gradient: Gradient(colors: [ .red, .purple]), startPoint: .top, endPoint: .trailing))
.cornerRadius(60)
.shadow(color: Color.gray, radius: 2, x: 3, y: 3)
}
}
.frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: .infinity, alignment: .center)
.keyboardSensible($offsetValue)
.navigationBarTitle("Create meme")
.navigationBarItems(trailing:
Button(action: {
for item in createCards{
print(item.getBottomText())
print(item.getTopText())
}
}){
Text("Save")
}
)        }
}
}

您需要知道如何使用ObservableObject@ObservedObject@State@Binding

但为了简单起见,让我们来看看如何使memeCard函数发挥作用。

创建模型

class Model: ObservableObject {
var topText: String = ""
var bottomText: String = ""
init(top: String, bottom: String) {
self.topText = top
self.bottomText = bottom
}
}

memeCard视图中使用模型实例

struct memeCard: View, Identifiable{
@ObservedObject var model = Model(top: "", bottom: "")
let id = UUID()
...

接下来,我们将model实例绑定到textFields。

VStack(spacing: 30){
TextField("Top text...", text: self.$model.topText).multilineTextAlignment(.center)
Divider()
TextField("Bottom text...", text: self.$model.bottomText)
}

然后我们可以使用现有的顶部和底部函数从模型类中提取数据,如下所示:

func getBottomText() -> String{
print("BOTTOM: (self.model.bottomText)")
return self.model.bottomText
}
func getTopText() -> String{
print("TOP: (self.model.topText)")
return self.model.topText
}

哇!现在应该可以了。这是另一个问题的答案https://stackoverflow.com/a/57623488/3231194应该能帮到你,它写得很全面。

最新更新