简体   繁体   English

如何从IOS Swift'Any'类型访问和获取嵌套值?

[英]How to access & get nested values from IOS Swift 'Any' type?

I am trying to read from Firestore into a Dictionary[Any] type using Struct. 我正在尝试使用Struct从Firestore读入Dictionary [Any]类型。 I can get the values loaded into variable "data" dictionary with Any type. 我可以使用Any类型将值加载到变量“数据”字典中。 However I cannot loop thru it to access normal nested Dictionary variable. 但是,我无法通过它循环访问普通的嵌套Dictionary变量。 I cannot get Key, values printed. 我无法获取键,无法打印值。

Following is my code: 以下是我的代码:

    class PullQuestions {
    //shared instance variable 
    **public var data = [Any]()**
    private var qdb = Firestore.firestore()

    public struct questionid
    {
        let qid : String
        var questions : [basequestion]
        var answers: [baseans]
    }
   public struct basequestion {

        let category : String
        let question : String
    }

   public struct baseans {
        let answer : String
    }

    class var sharedManager: PullQuestions {
        struct Static {
            static let instance = PullQuestions()
        }
        return Static.instance
    }

    static func getData(completion: @escaping (_ result: [Any]) -> Void) {
        let rootCollection = PullQuestions.sharedManager.qdb.collection("questions")
        //var data = [Any]()
        rootCollection.order(by: "upvote", descending: false).getDocuments(completion: {
            (querySnapshot, error) in

            if error != nil {
                print("Error when getting data \(String(describing: error?.localizedDescription))")
            } else {
                guard let topSnapshot = querySnapshot?.documents else { return }
               // var questiondoc = [basequestion]()
                for questioncollection in topSnapshot {
                    rootCollection.document(questioncollection.documentID).collection("answers").getDocuments(completion: {
                        (snapshot, err) in

                        guard let snapshot = snapshot?.documents else { return }

                        var answers = [baseans]()

                        for document in snapshot { //There should be only one Document for each answer collection
                            //Read thru all fields
                            for i in 0..<document.data().count
                            {
                            let newAns = baseans(answer: answer)
                           print("Answer Docs=>", (answer))
                            answers.append(newAns)
                            }
                        }
                        let qid = questioncollection.documentID
                        let category = questioncollection.data()["category"] as! String
                        let question =  questioncollection.data()["question"] as! String

                        let newQuestions = basequestion(category: category ,question: question)

                        let newQuestionDict = questionid(qid: qid, questions: [newQuestions], answers: answers)

                        PullQuestions.sharedManager.data.append(newQuestionDict)
                        //Return data on completion
                        completion(PullQuestions.sharedManager.data)
                    })
                }
            }
        })
  }
}

I can print like this 我可以这样打印

print("Count =>", (PullQuestions.sharedManager.data.count))
        //  print(PullQuestions.sharedManager.data.first ?? "Nil")
        print(PullQuestions.sharedManager.data[0])

        for  element in PullQuestions.sharedManager.data
        {
            print("Elements in data:=>", (element))
        }

I could access only the key.. how do i go and get the nested values ? 我只能访问密钥..我该如何获取嵌套值?

First of all, consider using Swift code conventions (eg your structs are named with small letters, but you should start with capital), this will make your code more readable. 首先,考虑使用Swift代码约定(例如,您的结构以小写字母命名,但您应该以大写字母开头),这将使您的代码更具可读性。

Returning to your question. 回到您的问题。 You use an array instead of dictionary (this piece of code: public var data = [Any]() ). 您使用数组而不是字典(这段代码: public var data = [Any]() )。 And here you are trying to print values: 在这里,您尝试打印值:

for  element in PullQuestions.sharedManager.data
{
    print("Elements in data:=>", (element))
}

In this context element is an Any object, thus you cannot access any underlying properties. 在此上下文中, elementAny对象,因此您无法访问任何基础属性。 In order to do this you have two options: 为此,您有两个选择:

1. You should specify the type of array's objects in it's declaration like this: 1.您应该在声明中指定数组对象的类型,如下所示:

public var data = [questionid]()

or you can user this: 或者您可以使用此:

public var data: [questionid] = []

These two are equals, use the one you prefer. 这两个是相等的,请使用您喜欢的一个。

2. If for any reasons you don't want to specify the type in declaration, you can cast it in your loop. 2.如果出于某种原因不想在声明中指定类型,则可以将其强制转换为循环。 Like this: 像这样:

for  element in PullQuestions.sharedManager.data
{
    if let element = element as? quetionid {
        print("Elements in data:=>", (element))
        // you can also print element.qid, element.questions, element.answers
    } else {
        print("Element is not questionid")
    }
}

You could of course use the force cast: 您当然可以使用强制转换:

let element = element as! questionid

and avoid if let syntax (or guard let if you prefer), but I wouldn't recommend this, because it (potentially) can crash your app if element will be nil or any other type. 并避免if let语法(如果愿意的话,也可以选择guard let ),但是我不推荐这样做,因为如果element为nil或任何其他类型,它(可能)可能会使您的应用程序崩溃。

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

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