繁体   English   中英

如何在 SwiftUI 的 Firestore 中添加动态子集合数据?

[英]How Do I Add Dynamic Sub Collection Data In Firestore In SwiftUI?

我是 swift 和 firebase 的新手,正在尝试很多事情。 我在应用程序中显示的 firebase 中创建了一组“字符”。 目的是通过赚取积分来解锁“角色”。 通过步行获得积分(使用 HealthKit 获取步数)

当用户点击一个字符然后点击“解锁”时,它被添加到一个名为 UnlockingCharacters 的结构中。

UnlockingCharacters 显示在用户配置文件中。

我需要在 Firebase 上制作用户文档的 UnlockingCharacters 结构的一部分(也许作为子集合?)

我想将 UnlockingCharacters 中的字符数限制为 2。通过采取变成点的步骤来解锁字符。 当点数上传到 Firebase 时,角色会收到这些点数并将其添加到其总数中(角色点数是所有解锁角色点数的用户的总和)。

下面是人物模型:

struct Character: Identifiable, Decodable {
    
@DocumentID var id: String?
    var character_name: String
    var character_type: String
    var character_image: String
    var character_details: String
    var character_usersUnlocking: Int
    var character_totalPoints: Int
    var user: UserModel?
    var didUnlock: Bool? = false
      
    // To identify whether it is being unlocked...
    var isUnlocking: Bool = false
    
}

这是 UnlockingCharacters 模型:

struct UnlockingCharacters: Identifiable {
    
    var id = UUID().uuidString
    var character: Character
}

共享数据模型:

class SharedDataModel: ObservableObject {
   
    // Unlocking Characters...
    @Published var unlockingCharacters: [Character] = [] 
}

我的功能:

 func isUnlocked() -> Bool {
        
        return sharedData.unlockingCharacters.contains { characterData in
            return self.characterData.id == characterData.id
        }
    }

    func addToUnlocking() {

        if let index = sharedData.unlockingCharacters.firstIndex(where: {

            characterData in
            return self.characterData.id == characterData.id
        }){
            // Remove from unlocking...
            sharedData.unlockingCharacters.remove(at: index)
        }
        else {
            // Add to unlocking...
            sharedData.unlockingCharacters.append(characterData)
        }
    }

我知道我的 UserModel 也需要添加一些东西,但是我收到一个错误:

struct UserModel: Identifiable, Decodable {
    var username : String
    var pic : String
    var bio: String
    var uid : String
    var id: String { uid }  

//I am getting error for the following variable:
(Value type 'UserModel' cannot have a stored property that recursively contains it)

    var activeUnlockingCharacters: UnlockingCharacters
}

总而言之,我需要将 UnlockingCharacters 添加到 Firebase 上的用户文档中。

我在处理自定义对象时遇到错误。 这是我的代码:

let ref = Firestore.firestore()

func fetchUser(uid: String,completion: @escaping (UserModel) -> ()){
    
    let db = Firestore.firestore()
    
    ref.collection("Users").document(uid).getDocument { (doc, err) in
        guard let user = doc else{return}
        
        let username = user.data()?["username"] as? String ?? "No Username"
        let pic = user.data()?["imageurl"] as? String ?? "No image URL"
        let bio = user.data()?["bio"] as? String ?? "No bio"
        let uid = user.data()?["uid"] as? String ?? ""
 
        do {
            try db.collection("Users").document("\(uid)").setData(from: UnlockingCharacters)
        } catch let error {
            print("Error writing object to Firestore: \(error)")
        }
        
        DispatchQueue.main.async {
            completion(UserModel(username: username, pic: pic, bio: bio, uid: uid, activeUnlockingCharacters: UnlockingCharacters))
        }
    }
}

做的错误是:“类型'UnlockingCharacters.Type'不能符合'Encodable'”

DispatchQueue 中的错误是:“无法将 'UnlockingCharacters.Type' 类型的值转换为预期的参数类型 '[UnlockingCharacters]'”

摆脱var user: UserModel? Character

然后就可以找到activeUnlockingCharacters下的字符了

或类似的东西

UserModel/{uid}/UnlockingCharacters

你(们)能做到

var activeUnlockingCharacters: UnlockingCharacters

数组

var activeUnlockingCharacters: [UnlockingCharacters]

然后使用验证或规则将计数限制为 2

Firebase 有一整节介绍如何处理自定义对象。

https://firebase.google.com/docs/firestore/manage-data/add-data#custom_objects

如果你的所有结构都符合 Codable

do {
    try db.collection("UserModel").document("\(uid)").setData(from: userModelObject)
} catch let error {
    print("Error writing object to Firestore: \(error)")
}

并阅读

https://firebase.google.com/docs/firestore/query-data/get-data

let docRef = db.collection("UserModel").document("\(uid)")

docRef.getDocument(as: UserModel.self) { result in
    // The Result type encapsulates deserialization errors or
    // successful deserialization, and can be handled as follows:
    //
    //      Result
    //        /\
    //   Error  UserModel
    switch result {
    case .success(let userModel):
        // A `Model` value was successfully initialized from the DocumentSnapshot.
        print("Model: \(userModel)")
    case .failure(let error):
        // A `Model` value could not be initialized from the DocumentSnapshot.
        print("Error decoding object: \(error)")
    }
}

您还可以使用新的@FirestoreQuery并使用规则来限制可见的对象

https://firebase.google.com/docs/reference/swift/firebasefirestoreswift/api/reference/Structs/FirestoreQuery

在规则中设置用户是唯一可以基于auth读取自己的UserModel的用户。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM