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

时间:2019-02-03 08:41:22

标签: ios swift dictionary

我正在尝试使用Struct从Firestore读取为Dictionary [Any]类型。我可以使用Any类型将值加载到变量“数据”字典中。 但是,我无法通过它循环访问普通的嵌套Dictionary变量。 我无法获取键,无法打印值。

以下是我的代码:

    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)
                    })
                }
            }
        })
  }
}

我可以这样打印

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))
        }

我只能访问密钥。我该如何获取嵌套值?

1 个答案:

答案 0 :(得分:0)

首先,考虑使用Swift代码约定(例如,您的结构体以小写字母命名,但您应该以大写字母开头),这将使您的代码更具可读性。

回到您的问题。您使用数组而不是字典(这段代码:public var data = [Any]())。在这里,您尝试打印值:

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

在这种情况下,elementAny对象,因此您不能访问任何基础属性。为此,您有两个选择:

1。您应该在声明中指定数组对象的类型,如下所示:

public var data = [questionid]()

或者您可以使用它:

public var data: [questionid] = []

这两个是相等的,请使用您喜欢的一个。

2。。如果出于某种原因不想在声明中指定类型,可以将其强制转换为循环。像这样:

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")
    }
}

您当然可以使用强制施力:

let element = element as! questionid

并避免使用if let语法(如果愿意,也可以避免使用guard let),但是我不建议这样做,因为如果element为nil或任何其他类型,它(可能)会使您的应用程序崩溃。