Как получить доступ и получить вложенные значения из типа IOS Swift «Any»? - PullRequest
0 голосов
/ 03 февраля 2019

Я пытаюсь прочитать из Firestore в словарь [любой] тип, используя Struct.Я могу получить значения, загруженные в переменную «data» Dictionary любого типа.Однако я не могу пройти через него, чтобы получить доступ к обычной вложенной переменной 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 голосов
/ 03 февраля 2019

Прежде всего, рассмотрите использование соглашений кода Swift (например, ваши структуры названы строчными буквами, но вы должны начинать с заглавной буквы), это сделает ваш код более читабельным.

Возвращаясь к вашему вопросу.Вы используете массив вместо словаря (этот кусок кода: public var data = [Any]()).И здесь вы пытаетесь напечатать значения:

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

В этом контексте element является Any объектом, поэтому вы не можете получить доступ к каким-либо базовым свойствам.Для этого у вас есть два варианта:

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, если хотите), но я бы не рекомендовал это, потому что это (потенциально) может привести к сбою вашего приложения, если элемент будет nil или любого другого типа.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...