Swiftui 附加到结构数组不起作用
Swiftui append to a struct array doesn't work
我正在学习swiftui。但是现在我遇到了一个问题。
我正在尝试将数据附加到结构数组。
struct outfit:Identifiable {
var id = UUID()
var user: String
var amount: Double
var rating: Double
}
和另一个文件
import SwiftUI
import Firebase
import FirebaseStorage
import FirebaseFirestore
struct rate: View {
private var db = Firestore.firestore()
@State var user = Auth.auth().currentUser
@State private var outfitcards = [outfit]()
@State private var cards = [1, 2, 3]
@State private var offset = [CGSize.zero, CGSize.zero]
init () {
loadcards()
}
var body: some View {
GeometryReader { frame in
ZStack{
VStack {
Text("outfit")
.font(.largeTitle)
.padding()
ZStack {
Text("No cards to show")
.frame(width: frame.size.width * 0.6, height: frame.size.width * 1.6)
HStack {
Image(systemName: "record.circle.fill")
.foregroundColor(.red)
Spacer()
Image(systemName: "record.circle.fill")
.foregroundColor(.green)
}
ForEach(outfitcards) { index in
Text(index.user)
}
}
}
}
}
}
func loadcards () {
db.collection("rating").whereField("user", isNotEqualTo: user?.uid ?? "Error")
.getDocuments() { (querySnapshot, err) in
if let err = err {
print("Error getting documents: \(err.localizedDescription)")
} else {
for document in querySnapshot!.documents {
let cuser = document.get("user") as! String
let camount = document.get("amount") as! Double
let crating = document.get("rating") as! Double
print("user=\(cuser) amount=\(camount) crating=\(crating)")
outfitcards.append(outfit(user: cuser, amount: camount, rating: crating))
}
print(outfitcards)
}
}
}
}
它确实打印了用户名、金额和评级,但是当我打印数组本身时,它给了我一个 []。所以它不追加。另外 for each 循环是空的,所以这也意味着数组是空的
没有附加任何内容
有人知道我做错了什么吗?
像这样在 View
中加载数据是一种危险的做法,只要重新呈现视图(甚至在这种情况下甚至重新启动),它就会得到 reset/reloaded。
相反,将加载数据的代码移动到 ObservableObject
:
struct Outfit:Identifiable {
var id = UUID()
var user: String
var amount: Double
var rating: Double
}
class Loader : ObservableObject {
private var db = Firestore.firestore()
private var user = Auth.auth().currentUser
@Published var outfitcards = [Outfit]()
func loadcards () {
db.collection("rating").whereField("user", isNotEqualTo: user?.uid ?? "Error")
.getDocuments() { (querySnapshot, err) in
if let err = err {
print("Error getting documents: \(err.localizedDescription)")
} else {
for document in querySnapshot!.documents {
let cuser = document.get("user") as! String
let camount = document.get("amount") as! Double
let crating = document.get("rating") as! Double
print("user=\(cuser) amount=\(camount) crating=\(crating)")
self.outfitcards.append(Outfit(user: cuser, amount: camount, rating: crating))
}
print(self.outfitcards)
}
}
}
}
struct Rate: View {
@StateObject var loader = Loader()
@State private var cards = [1, 2, 3]
@State private var offset = [CGSize.zero, CGSize.zero]
var body: some View {
GeometryReader { frame in
ZStack{
VStack {
Text("outfit")
.font(.largeTitle)
.padding()
ZStack {
Text("No cards to show")
.frame(width: frame.size.width * 0.6, height: frame.size.width * 1.6)
HStack {
Image(systemName: "record.circle.fill")
.foregroundColor(.red)
Spacer()
Image(systemName: "record.circle.fill")
.foregroundColor(.green)
}
ForEach(loader.outfitcards) { index in
Text(index.user)
}
}
}
}
}.onAppear {
loader.loadcards()
}
}
}
现在,加载程序负责进行数据库调用。它更新视图观察到的@Published 属性。
请注意,我更改了一些东西(Rate、Outfit)的大写。在Swift中,通常的做法是类型大写(classes/structs/enums),变量名以小写字母开头。
还可能值得注意的是,您从 firebase(使用 as!
)转换数据的方式很危险,如果数据不是您期望的格式,可能会使您的程序崩溃。最好使用可选绑定 (let user = document.get("user") as? String
)
您的问题是您在初始化视图时更新了@State 值,这是您以错误的方式进行的,在出现时这样做:
struct rate: View {
private var db = Firestore.firestore()
@State var user = Auth.auth().currentUser
@State private var outfitcards = [outfit]()
@State private var cards = [1, 2, 3]
@State private var offset = [CGSize.zero, CGSize.zero]
var body: some View {
GeometryReader { frame in
ZStack{
VStack {
Text("outfit")
.font(.largeTitle)
.padding()
ZStack {
Text("No cards to show")
.frame(width: frame.size.width * 0.6, height: frame.size.width * 1.6)
HStack {
Image(systemName: "record.circle.fill")
.foregroundColor(.red)
Spacer()
Image(systemName: "record.circle.fill")
.foregroundColor(.green)
}
ForEach(outfitcards) { index in
Text(index.user)
}
}
}
}
}
.onAppear() { loadcards() } // <<: Here
}
func loadcards () {
db.collection("rating").whereField("user", isNotEqualTo: user?.uid ?? "Error")
.getDocuments() { (querySnapshot, err) in
if let err = err {
print("Error getting documents: \(err.localizedDescription)")
} else {
for document in querySnapshot!.documents {
let cuser = document.get("user") as! String
let camount = document.get("amount") as! Double
let crating = document.get("rating") as! Double
print("user=\(cuser) amount=\(camount) crating=\(crating)")
outfitcards.append(outfit(user: cuser, amount: camount, rating: crating))
}
print(outfitcards)
}
}
}
}
我正在学习swiftui。但是现在我遇到了一个问题。 我正在尝试将数据附加到结构数组。
struct outfit:Identifiable {
var id = UUID()
var user: String
var amount: Double
var rating: Double
}
和另一个文件
import SwiftUI
import Firebase
import FirebaseStorage
import FirebaseFirestore
struct rate: View {
private var db = Firestore.firestore()
@State var user = Auth.auth().currentUser
@State private var outfitcards = [outfit]()
@State private var cards = [1, 2, 3]
@State private var offset = [CGSize.zero, CGSize.zero]
init () {
loadcards()
}
var body: some View {
GeometryReader { frame in
ZStack{
VStack {
Text("outfit")
.font(.largeTitle)
.padding()
ZStack {
Text("No cards to show")
.frame(width: frame.size.width * 0.6, height: frame.size.width * 1.6)
HStack {
Image(systemName: "record.circle.fill")
.foregroundColor(.red)
Spacer()
Image(systemName: "record.circle.fill")
.foregroundColor(.green)
}
ForEach(outfitcards) { index in
Text(index.user)
}
}
}
}
}
}
func loadcards () {
db.collection("rating").whereField("user", isNotEqualTo: user?.uid ?? "Error")
.getDocuments() { (querySnapshot, err) in
if let err = err {
print("Error getting documents: \(err.localizedDescription)")
} else {
for document in querySnapshot!.documents {
let cuser = document.get("user") as! String
let camount = document.get("amount") as! Double
let crating = document.get("rating") as! Double
print("user=\(cuser) amount=\(camount) crating=\(crating)")
outfitcards.append(outfit(user: cuser, amount: camount, rating: crating))
}
print(outfitcards)
}
}
}
}
它确实打印了用户名、金额和评级,但是当我打印数组本身时,它给了我一个 []。所以它不追加。另外 for each 循环是空的,所以这也意味着数组是空的
没有附加任何内容
有人知道我做错了什么吗?
像这样在 View
中加载数据是一种危险的做法,只要重新呈现视图(甚至在这种情况下甚至重新启动),它就会得到 reset/reloaded。
相反,将加载数据的代码移动到 ObservableObject
:
struct Outfit:Identifiable {
var id = UUID()
var user: String
var amount: Double
var rating: Double
}
class Loader : ObservableObject {
private var db = Firestore.firestore()
private var user = Auth.auth().currentUser
@Published var outfitcards = [Outfit]()
func loadcards () {
db.collection("rating").whereField("user", isNotEqualTo: user?.uid ?? "Error")
.getDocuments() { (querySnapshot, err) in
if let err = err {
print("Error getting documents: \(err.localizedDescription)")
} else {
for document in querySnapshot!.documents {
let cuser = document.get("user") as! String
let camount = document.get("amount") as! Double
let crating = document.get("rating") as! Double
print("user=\(cuser) amount=\(camount) crating=\(crating)")
self.outfitcards.append(Outfit(user: cuser, amount: camount, rating: crating))
}
print(self.outfitcards)
}
}
}
}
struct Rate: View {
@StateObject var loader = Loader()
@State private var cards = [1, 2, 3]
@State private var offset = [CGSize.zero, CGSize.zero]
var body: some View {
GeometryReader { frame in
ZStack{
VStack {
Text("outfit")
.font(.largeTitle)
.padding()
ZStack {
Text("No cards to show")
.frame(width: frame.size.width * 0.6, height: frame.size.width * 1.6)
HStack {
Image(systemName: "record.circle.fill")
.foregroundColor(.red)
Spacer()
Image(systemName: "record.circle.fill")
.foregroundColor(.green)
}
ForEach(loader.outfitcards) { index in
Text(index.user)
}
}
}
}
}.onAppear {
loader.loadcards()
}
}
}
现在,加载程序负责进行数据库调用。它更新视图观察到的@Published 属性。
请注意,我更改了一些东西(Rate、Outfit)的大写。在Swift中,通常的做法是类型大写(classes/structs/enums),变量名以小写字母开头。
还可能值得注意的是,您从 firebase(使用 as!
)转换数据的方式很危险,如果数据不是您期望的格式,可能会使您的程序崩溃。最好使用可选绑定 (let user = document.get("user") as? String
)
您的问题是您在初始化视图时更新了@State 值,这是您以错误的方式进行的,在出现时这样做:
struct rate: View {
private var db = Firestore.firestore()
@State var user = Auth.auth().currentUser
@State private var outfitcards = [outfit]()
@State private var cards = [1, 2, 3]
@State private var offset = [CGSize.zero, CGSize.zero]
var body: some View {
GeometryReader { frame in
ZStack{
VStack {
Text("outfit")
.font(.largeTitle)
.padding()
ZStack {
Text("No cards to show")
.frame(width: frame.size.width * 0.6, height: frame.size.width * 1.6)
HStack {
Image(systemName: "record.circle.fill")
.foregroundColor(.red)
Spacer()
Image(systemName: "record.circle.fill")
.foregroundColor(.green)
}
ForEach(outfitcards) { index in
Text(index.user)
}
}
}
}
}
.onAppear() { loadcards() } // <<: Here
}
func loadcards () {
db.collection("rating").whereField("user", isNotEqualTo: user?.uid ?? "Error")
.getDocuments() { (querySnapshot, err) in
if let err = err {
print("Error getting documents: \(err.localizedDescription)")
} else {
for document in querySnapshot!.documents {
let cuser = document.get("user") as! String
let camount = document.get("amount") as! Double
let crating = document.get("rating") as! Double
print("user=\(cuser) amount=\(camount) crating=\(crating)")
outfitcards.append(outfit(user: cuser, amount: camount, rating: crating))
}
print(outfitcards)
}
}
}
}