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

时间:2020-03-10 06:34:14

标签: ios swift swiftui state

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

我有一个包含topText和bottomText的卡的结构。我还有另一个结构,它是用于输入组件(例如卡)的形式。我将这些卡存储在一个数组中,并随着单击+按钮的增加而越来越多。在父视图中,我对该数组有一个foreach,因此它们可以动态呈现。

我在尝试从这些结构中提取状态值时遇到问题。卡片包含topText和bottomText的状态。在父阵列(存在卡片阵列的地方)中单击保存按钮时,它将在卡片阵列上进行迭代,并通过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")
                }
            )        }

    }

}

1 个答案:

答案 0 :(得分:1)

您需要知道如何使用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
}

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