Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/arrays/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Arrays 如何在Swift 3中一个函数之后运行另一个函数_Arrays_Firebase_Swift3_Firebase Realtime Database_Grand Central Dispatch - Fatal编程技术网

Arrays 如何在Swift 3中一个函数之后运行另一个函数

Arrays 如何在Swift 3中一个函数之后运行另一个函数,arrays,firebase,swift3,firebase-realtime-database,grand-central-dispatch,Arrays,Firebase,Swift3,Firebase Realtime Database,Grand Central Dispatch,我是swift 3的新手,我被这个问题困住了。我有两个函数,第一个函数获取FirebaseDatabase中的一个键的值。第二个函数在TableView中显示从FirebaseDatase检索到的变量。问题是第二个函数在第一个函数之前启动。这使得该值返回nil 第一个功能: self.shopItems = [String]() databaseRef.observe(FIRDataEventType.value, with: { (snapshot) in

我是swift 3的新手,我被这个问题困住了。我有两个函数,第一个函数获取FirebaseDatabase中的一个键的值。第二个函数在TableView中显示从FirebaseDatase检索到的变量。问题是第二个函数在第一个函数之前启动。这使得该值返回nil

第一个功能:

        self.shopItems = [String]()



        databaseRef.observe(FIRDataEventType.value, with: { (snapshot) in
                for child in snapshot.children {
                    let snap = child as! FIRDataSnapshot
                    let dictionary = snap.value as! [String: AnyObject]
                    self.shopItems.append(dictionary["Name"] as! String)

                    print(self.shopItems)
            }

        })
 func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

    var cell = tableView.dequeueReusableCell(withIdentifier: self.cellReuseIdentifier, for: indexPath) as UITableViewCell

    DispatchQueue.main.asyncAfter(deadline: .now() + .seconds(4), execute: {
        cell.textLabel?.text = self.shopItems[indexPath.row]
    })
    return cell
}
第二个功能:

        self.shopItems = [String]()



        databaseRef.observe(FIRDataEventType.value, with: { (snapshot) in
                for child in snapshot.children {
                    let snap = child as! FIRDataSnapshot
                    let dictionary = snap.value as! [String: AnyObject]
                    self.shopItems.append(dictionary["Name"] as! String)

                    print(self.shopItems)
            }

        })
 func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

    var cell = tableView.dequeueReusableCell(withIdentifier: self.cellReuseIdentifier, for: indexPath) as UITableViewCell

    DispatchQueue.main.asyncAfter(deadline: .now() + .seconds(4), execute: {
        cell.textLabel?.text = self.shopItems[indexPath.row]
    })
    return cell
}

我知道我可以使用Dispatch Wait方法,但我希望第二个函数等待第一个函数完成。我该怎么做呢?

试试这个,正如我在第一篇评论中所说的,我认为您只需要在
打印(self.shopItems)
之后调用
self.tableView.reloadData

并正确实施这一方法

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return self.shopItems.count
}
同时将您的cellForRow更新到此

 func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

    var cell = tableView.dequeueReusableCell(withIdentifier: 
    self.cellReuseIdentifier, for: indexPath) as UITableViewCell

    cell.textLabel?.text = self.shopItems[indexPath.row]
    return cell
}

希望这对你有所帮助,你很困惑。您不需要调用
tableView(\uu:cellForRowAt:)
。系统调用它

如果要在数据加载完成后等待并重新加载表,则应在
databaseRef中调用reloadData。请观察
方法的闭包:

    databaseRef.observe(FIRDataEventType.value, with: { (snapshot) in
            for child in snapshot.children {
                let snap = child as! FIRDataSnapshot
                let dictionary = snap.value as! [String: AnyObject]
                self.shopItems.append(dictionary["Name"] as! String)

                print(self.shopItems)

                //Add the line below. 
                //Note that if the closure is called from the background, you'll 
                //need to use GCD to call this method on the main thread.
        }
        self.tableView.reloadData()
    }
而且,如果databaseRef.observe方法中的完成代码在后台线程上被调用,那么您需要将其包装在调用
Dispatch.main.async()
(或调用主线程上的代码的类似方法)中


第二个函数在加载tableview中的数据时运行。创建tableview时,它将数据从shopitems数组加载到视图中。如果数组中没有对象,则tableview将显示为空。为了反映对shopitems数组的更改,换句话说,反映In item已附加到数组,您必须调用相应的tableview函数

正确的方法是使用:

    databaseRef.observe(FIRDataEventType.value, with: { (snapshot) in
            for child in snapshot.children {
                let snap = child as! FIRDataSnapshot
                let dictionary = snap.value as! [String: AnyObject]
                self.shopItems.append(dictionary["Name"] as! String)

                let row = self.shopItems.index(of:self.shopItems.last!)
                let indexPath = IndexPath(row:row, section:0)
                tableView.insertItemsAtIndexPaths([indexPath])

                print(self.shopItems)
        }

    })
。您必须使用shopitems数组中对象的索引创建indexPath

另一种方法是在追加后重新加载tableview中的所有数据

    databaseRef.observe(FIRDataEventType.value, with: { (snapshot) in
            for child in snapshot.children {
                let snap = child as! FIRDataSnapshot
                let dictionary = snap.value as! [String: AnyObject]
                self.shopItems.append(dictionary["Name"] as! String)



                print(self.shopItems)
        }

              DispatchQueue.main.async {
            self.tableView.reloadData()
           }

    })

我想你只需要在
print(self.shopItems)
之后调用
self.tableView.reloadData
我该如何使用闭包?Objc dupe:你为什么在
cellForRowAt
方法中使用
DispatchQueue
?摆脱它。不,那根本不正确。你需要在主队列上调用
reloadData
。我认为观测者回调在主线程中返回,好的,我会更新我的答案@rmaddy Thanks我不使用Firebase,所以我想可能总是在主队列上调用关闭,但我不会做出这样的假设。@rmaddy我认为这没有必要,因为提问者说它有效,我也不使用Firebase,但我不确定哈哈,我忘了,很抱歉:)祝您有愉快的一天您需要在循环后调用
reloadData
,而不是在循环内调用。它需要在主队列上调用。正如@rmaddy在Duncan answer的评论中所说,“你需要在循环后调用reloadData,而不是在循环内部。它需要在主队列上调用。”@ReinierMelian在循环内重新加载数据会在下载每个项目时重新加载。在循环外重新加载将以批方式重新加载更新。@rmdaddy当您发布时,我正在写这篇文章,但没有看到您的回复,我道歉。没有必要如此敌意,我只是想帮忙。如果我的答案对任何人都有帮助,我很高兴。如果这不正常,请原谅,我是个新手SO@Abishek23没有敌意。我只是指出了一个事实,仅此而已。请不要把这件事当回事。您可能应该删除您的答案,因为它没有帮助。@Abishek23
snapshot.children
是一个数组,那么为什么要在每个项目上重新加载表呢?数据已经存在,您只需在将所有对象添加到
shopItems
数组后重新加载表即可