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

Posted

技术标签:

【中文标题】如何从结构视图数组中提取状态? SwiftUI【英文标题】:How to extract state from an array of struct views? SwiftUI 【发布时间】:2020-03-10 06:34:14 【问题描述】:

我在从 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】:

您需要知道如何使用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 View 中使用模型实例。

struct memeCard: View, Identifiable
    @ObservedObject var model = Model(top: "", bottom: "")

    let id = UUID()
    ...

接下来,我们将model 实例绑定到文本字段。

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://***.com/a/57623488/3231194 应该能帮到你,写的很全面。

【讨论】:

以上是关于如何从结构视图数组中提取状态? SwiftUI的主要内容,如果未能解决你的问题,请参考以下文章

SQL(雅典娜)中的取消嵌套:如何将结构数组转换为从结构中提取的值数组?

如何从 lua 数组中提取值?

如何从 axios 响应对象中的所有项目中提取特定值到 vuex 状态

MATLAB如何提取结构体中数据

从指向结构数组的指针中提取元素

我如何解析 JSON,将其排序为数组。提取数据并填充到表格视图中?