Arrays 如何在Swift 3中一个函数之后运行另一个函数
我是swift 3的新手,我被这个问题困住了。我有两个函数,第一个函数获取FirebaseDatabase中的一个键的值。第二个函数在TableView中显示从FirebaseDatase检索到的变量。问题是第二个函数在第一个函数之前启动。这使得该值返回nil 第一个功能: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
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没有敌意。我只是指出了一个事实,仅此而已。请不要把这件事当回事。您可能应该删除您的答案,因为它没有帮助。@Abishek23snapshot.children
是一个数组,那么为什么要在每个项目上重新加载表呢?数据已经存在,您只需在将所有对象添加到shopItems
数组后重新加载表即可