swift - 如何在单个函数中执行两个完成 block 并将完成 block 的数据传递给下一个 View Controller ?

标签 swift firebase closures snapshot

这是我的数据库结构:

This is the database structure

我正在使用一个带闭包的函数,执行两个完成 block 并将数据存储在两个单独的数组中。获得数据后,我想将数据传递到下一个 View Controller 到不同的变量中,但我得到的是两个数组的相同值。

@IBAction func GoToAnswerPage(_ sender: Any) {

    self.getData(refe:JoinCodeTextField.text!) { (array) in
        self.performSegue(withIdentifier:"JoinToAnswerPage",sender:array)
    }

}

func getData(refe: String, completion: @escaping (([Any]) -> ())) {
    var questionArray = [Any]()
    var answerArray = [Any]()
    let ref = Database.database().reference(fromURL: "https://pollapp-30419.firebaseio.com/").child("Questions/\(refe)/")
    ref.child("Question_And_Options").observeSingleEvent(of: .value,with: { snapshot in
        let enumerator = snapshot.children
        while let rest = enumerator.nextObject() as? DataSnapshot, let value = rest.value{
            questionArray.append(value)
        }
        completion(questionArray)
    })
    ref.child("Answer_Key").observeSingleEvent(of: .value,with: { snapshot in
        let enumerator = snapshot.children
        while let rest = enumerator.nextObject() as? DataSnapshot, let value = rest.value{
            answerArray.append(value)
        }
        completion(answerArray)
    })
}

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    guard let joinViewController = segue.destination as? JoinAnswerViewController
        else {
            return
    }
    joinViewController.answers = sender as! [String]
    joinViewController.options = sender as! [String]
}

在下一个 View Controller 上。

var options = [Any]()
var answers = [Any]()

这是我得到的输出:

answers-["Test Q-1", "Test A-1", "Test A-2"]

questions-["Test Q-1", "Test A-1", "Test A-2"]

answers-["Test A-1"]

questions-["Test A-1"]

相反,我应该得到:

questions-["Test Q-1", "Test A-1", "Test A-2"]

answers-["Test A-1"]

最佳答案

您的完成处理程序将被调用两次,一次用于“答案”,一次用于“问题”。它们可以以任意顺序出现,因此您应该在完成时传递一个额外的 type 以了解您收到了哪个。使用 [String : [Any]] 字典收集两个数组,并在收到两个数组并存储后调用 self.performSegue(withIdentifier:sender:)它们在字典 arrays 中。

prepare(for:sender:) 中解压 sender 字典并赋值:

@IBAction func GoToAnswerPage(_ sender: Any) {

    var arrays = [String : [Any]]()

    self.getData(refe: JoinCodeTextField.text!) { (array, type) in

        arrays[type] = array

        if arrays.count == 2 {
            self.performSegue(withIdentifier:"JoinToAnswerPage",sender: arrays)
        }
    }

}

func getData(refe: String, completion: @escaping (([Any], String) -> ())) {
    var questionArray = [Any]()
    var answerArray = [Any]()
    let ref = Database.database().reference(fromURL: "https://pollapp-30419.firebaseio.com/").child("Questions/\(refe)/")
    ref.child("Question_And_Options").observeSingleEvent(of: .value,with: { snapshot in
        let enumerator = snapshot.children
        while let rest = enumerator.nextObject() as? DataSnapshot, let value = rest.value{
            questionArray.append(value)
        }
        completion(questionArray, "question")
    })
    ref.child("Answer_Key").observeSingleEvent(of: .value,with: { snapshot in
        let enumerator = snapshot.children
        while let rest = enumerator.nextObject() as? DataSnapshot, let value = rest.value{
            answerArray.append(value)
        }
        completion(answerArray, "answer")
    })
}

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    guard let joinViewController = segue.destination as? JoinAnswerViewController
        else {
            return
    }

    guard let arrays = sender as? [String : [Any]],
          let answers = arrays["answer"] as? [String],
          let questions = arrays["question"] as? [String]
        else { return }

    joinViewController.answers = answers
    joinViewController.options = questions
}

注意:当用户按下按钮时,他们应该立即得到响应。由于您是从网络加载数据,因此可能会有延迟,使用户怀疑是否发生了什么。最好将 JoinCodeTextField.text! 传递给 JoinAnswerViewController 并让它加载问题/答案数据。 JoinAnswerViewController 可以在数据加载时显示一个 UIActivityIndi​​catorView(微调器),让用户知道数据即将到来。拥有两个数组后,您可以设置 JoinAnswerViewController

关于swift - 如何在单个函数中执行两个完成 block 并将完成 block 的数据传递给下一个 View Controller ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57367359/

相关文章:

iOS swift 应用程序在文本字段中点击崩溃(NSNull 长度 - 实例无法识别的选择器)

java - 从 firebase android 中删除自动 key 节点

javascript - 可视化 Firebase 数据Firebase

iOS Swift 如何检测登录错误原因以向用户显示正确的错误警报

swift - 使用闭包将变量信息传递给第一个 VC 时出现问题

swift - 在 SwiftUI 中的 ForEach 中使用 id 时,如何对数组的索引进行动画处理

ios - 我可以只在没有关联域的应用程序中使用 iOS 自动填充功能吗?

swift - 在 View Controller 中使用和乘以变量

javascript - .get() 函数获取 firebase 文档 "is not a function"

c# - LinqKit 的扩展器无法从字段中获取表达式是否有特殊原因?