简体   繁体   English

如何将用户的 Firestore Map 读取为 Swift 字典?

[英]How do I read a User's Firestore Map to a Swift Dictionary?

I have my user struct with has a dictionary of all their social medias.我有我的用户结构,其中包含他们所有社交媒体的字典。

struct User: Identifiable {

var id: String { uid }

let uid, email, name, bio, profileImageUrl: String
let numSocials, followers, following: Int

var socials: [String: String]


init(data: [String: Any]) {
    self.uid = data["uid"] as? String ?? ""
    self.email = data["email"] as? String ?? ""
    self.name = data["name"] as? String ?? ""
    self.bio = data["bio"] as? String ?? ""
    self.profileImageUrl = data["profileImageURL"] as? String ?? ""
    
    self.numSocials = data["numsocials"] as? Int ?? 0
    self.followers = data["followers"] as? Int ?? 0
    self.following = data["following"] as? Int ?? 0
    
    self.socials = data["socials"] as? [String: String] ?? [:]

}
}

The idea is for socials (the dictionary), to be dynamic, since users can add and remove social medias.这个想法是为了社交(字典)是动态的,因为用户可以添加和删除社交媒体。 Firestore looks like this: Firestore 看起来像这样:

在此处输入图像描述

The dictionary is initialized as empty.字典初始化为空。 I have been able to add elements to the dictionary with this function:我已经能够使用这个 function 向字典中添加元素:

private func addToStorage(selectedMedia: String, username: String) -> Bool {
    if username == "" {
        return false
    }
    guard let uid = FirebaseManager.shared.auth.currentUser?.uid else {
        print("couldnt get uid")
        return false
    }
    
    FirebaseManager.shared.firestore.collection("users").document(uid).setData([ "socials": [selectedMedia:username] ], merge: true)

    print("yoo")
    return true
}

However I can't seem to read the firestore map into my swiftui dictionary.但是我似乎无法将 firestore map 读入我的 swiftui 字典。 I want to do this so that I can do a ForEach loop and list all of them.我想这样做,以便我可以执行 ForEach 循环并列出所有这些。 If the map is empty then the list would be empty too, but I can't figure it out.如果 map 为空,则列表也为空,但我无法弄清楚。

Just in case, here is my viewmodel.以防万一,这是我的视图模型。

class MainViewModel: ObservableObject {

@Published var errorMessage = ""
@Published var user: User?

init() {
    DispatchQueue.main.async {
        self.isUserCurrentlyLoggedOut = FirebaseManager.shared.auth.currentUser?.uid == nil
    }

    fetchCurrentUser()
    
}

func fetchCurrentUser() {
    guard let uid = FirebaseManager.shared.auth.currentUser?.uid else {
        self.errorMessage = "Could not find firebase uid"
        print("FAILED TO FIND UID")
        return

    }

    FirebaseManager.shared.firestore.collection("users").document(uid).getDocument { snapshot, error in
        if let error = error {
            self.errorMessage =  "failed to fetch current user: \(error)"

            print("failed to fetch current user: \(error)")
            return
        }
        guard let data = snapshot?.data() else {
            print("no data found")
            self.errorMessage = "No data found"
            return

        }


        self.user = .init(data: data)

    }
}
   
}

TLDR: I can't figure out how to get my firestore map as a swiftui dictionary. TLDR:我不知道如何将我的 firestore map 作为 swiftui 字典。 Whenever I try to access my user's dictionary, the following error appears.每当我尝试访问我的用户词典时,都会出现以下错误。 If I force unwrap it crashes during runtime.如果我强制解包它会在运行时崩溃。 I tried to coalesce with "??"我试图合并“??” but I don't know how to make it be the type it wants.但我不知道如何让它成为它想要的类型。

ForEach(vm.user?.socials.sorted(by: >) ?? [String:String], id: \.key) { key, value in
                    linkDisplay(social: key, handler: value)
                        .listRowSeparator(.hidden)


                }.onDelete(perform: delete)

error to figure out弄清楚错误

Please be patient.请耐心等待。 I have been looking for answers through SO and elsewhere for a long time.很长一段时间以来,我一直在通过 SO 和其他地方寻找答案。 This is all new to me.这对我来说都是新的。 Thanks in advance.提前致谢。

This is a two part answer;这是一个分为两部分的答案; Part 1 addresses the question with a known set of socials (Github, Pinterest, etc).第 1 部分通过一组已知的社交网站(Github、Pinterest 等)解决了这个问题。 I included that to show how to map a Map to a Codable.我将其包括在内以展示如何将 map 和 Map 转换为 Codable。

Part 2 is the answer (TL;DR, skip to Part 2) so the social can be mapped to a dictionary for varying socials.第 2 部分是答案(TL;DR,跳到第 2 部分),因此可以将社交映射到不同社交的字典。

Part 1:第1部分:

Here's an abbreviated structure that will map the Firestore data to a codable object, including the social map field.这是一个缩写结构,它将 map Firestore 数据转换为可编码的 object,包括社交字段 map。 It is specific to the 4 social fields listed.它特定于列出的 4 个社会领域。

struct SocialsCodable: Codable {
    var Github: String
    var Pinterest: String
    var Soundcloud: String
    var TikTok: String
}

struct UserWithMapCodable: Identifiable, Codable {
    @DocumentID var id: String?
    var socials: SocialsCodable? //socials is a `map` in Firestore
}

and the code to read that data以及读取该数据的代码

func readCodableUserWithMap() {
    let docRef = self.db.collection("users").document("uid_0")

    docRef.getDocument { (document, error) in
        if let err = error {
            print(err.localizedDescription)
            return
        }

        if let doc = document {
            let user = try! doc.data(as: UserWithMapCodable.self)
            print(user.socials) //the 4 socials from the SocialsCodable object
        }
    }
}

Part 2:第2部分:

This is the answer that treats the socials map field as a dictionary这是将socials map 字段视为字典的答案

struct UserWithMapCodable: Identifiable, Codable {
    @DocumentID var id: String?
    var socials: [String: String]?
}

and then the code to map the Firestore data to the object然后代码到 map Firestore 数据到 object

func readCodableUserWithMap() {
    let docRef = self.db.collection("users").document("uid_0")

    docRef.getDocument { (document, error) in
        if let err = error {
            print(err.localizedDescription)
            return
        }

        if let doc = document {
            let user = try! doc.data(as: UserWithMapCodable.self)
            if let mappedField = user.socials {
                mappedField.forEach { print($0.key, $0.value) }
            }
        }
    }
}

and the output for part 2和第 2 部分的 output

TikTok ogotok
Pinterest pintepogo
Github popgit
Soundcloud musssiiiccc

I may also suggest taking the socials out of the user document completely and store it as a separate collection我可能还建议将社交完全从用户文档中取出并将其存储为一个单独的集合

socials
   some_uid
      Github: popgit
      Pinterest: pintepogo
   another_uid
      Github: git-er-done
      TikTok: dancezone

That's pretty scaleable and allows for some cool queries: which users have TikTok for example.这是相当可扩展的,并允许进行一些很酷的查询:例如,哪些用户拥有 TikTok。

暂无
暂无

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

相关问题 如何为 Codable Swift 结构的字典制作 ForEach 循环(基于 Firestore 映射) - How to make ForEach loop for a Codable Swift Struct's Dictionary (based on Firestore map) 如何读取 Swift 中的 Firestore 时间戳 - How to read a Firestore timestamp in Swift 如何使用用户输入的文档名称在 firestore 中输入数据库? - How do i input database in firestore with user's input for name of the document? 如何在 React 中使用 Map function 渲染 Firestore 集合? - How do I render Firestore collection using the Map function in React? Firestore - 如何在删除他的帐户时从他自己创建的所有文档中删除用户 ID? - Firestore - how do I remove user's ID from all the documents he's created himself when deleting his account? 如何从 Firestore 获取文档 ID 列表 - How do I get a list of document ID’s from Firestore 如何检索作为文档放置在 Firebase Cloud Firestore 中的 UID - How do I retrieve the UID's that I have placed as documents in my Firebase Cloud Firestore 使用 Cloud Functions 访问 firestore 中的用户数据,但如何安全地发送 UID/IDToken? - Accessing user data in firestore using Cloud Functions, but how do I securely send the UID/IDToken? 我创建并保存了用户的 email,但我无法执行 email 更新。 使用 firebase,firestore 和 react - I have the create and saving of the user's email, but I can't do an email update. Use firebase, firestore and react 如何使用嵌套的 map 字段为带有 flutter 的云 Firestore 创建用户 model? - How to create user model with nested map field for cloud firestore with flutter?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM