在从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")
}
) }
}
}
答案 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的答案 应该可以帮到您,它写得很全面。