Swift 在允许用户手动刷新页面之前,如何确保viewDidLoad()已完成?
我有一个重新加载数据的应用程序(通过运行两个查询,将查询到的信息附加到数组,以及重新加载tableview数据)。这两个查询都设置为在Swift 在允许用户手动刷新页面之前,如何确保viewDidLoad()已完成?,swift,xcode,Swift,Xcode,我有一个重新加载数据的应用程序(通过运行两个查询,将查询到的信息附加到数组,以及重新加载tableview数据)。这两个查询都设置为在viewDidLoad()上运行的函数,但也链接到一个刷新函数(用户可以通过拉动刷新手动激活该函数)。查询工作正常,但是,当查询函数由viewdiload()运行(但尚未完成)时,偶尔会出现问题,并且用户试图在完成之前拉刷新。。。重复项被添加到数组中,我希望避免这种情况。我的想法是最初将checking变量设置为false,在viewDidLoad()完成后将其更
viewDidLoad()
上运行的函数,但也链接到一个刷新函数(用户可以通过拉动刷新手动激活该函数)。查询工作正常,但是,当查询函数由viewdiload()
运行(但尚未完成)时,偶尔会出现问题,并且用户试图在完成之前拉刷新。。。重复项被添加到数组中,我希望避免这种情况。我的想法是最初将checking变量设置为false,在viewDidLoad()完成后将其更改为true,并且只允许pull to refresh函数在变量更改为true后工作。以下是功能的设置:
func myQueryandAppend(completion: (() -> Void)?){
myCreatorArray.removeAll(keepingCapacity: true)
//repeated for all arrays
let myQuery = PFQuery(className: "Posts")
myQuery.whereKey("User", equalTo: currentUserId)
myQuery.findObjectsInBackground { (objects, error) in
if let objectss = objects{
for object in objectss {
//append the arrays
self.tableView.reloadData()
}
}
})
}
另一个函数本质上与此函数相同,但提取稍有不同的信息并附加不同的数组。(旁注…不完全确定self.tableView.reloadData()
是否位于正确位置…)
这是viewDidLoad():
然后刷新处理程序:
func refresh(_ sender: AnyObject){
if checkerVar == true{
myQueryandAppend(completion: {
self.tableView.reloadData()
self.refreshControl.endRefreshing()
})
self.refreshControl.endRefreshing()
}else{
self.refreshControl.endRefreshing()
}
}
问题是,使用checkerVar时,viewDidLoad()闭包中completion内的实例永远不会被调用(上面的print语句永远不会被记录),我相信viewDidLoad()底部的第二个实例会立即完成,而不会真正等待函数完成。此外,任何(完成:{})
中的打印语句都不会被记录。
所以:1。为什么不调用补全中的print语句,以及(更重要的)2。如何使checkerVar仅在viewDidLoad()
完成后才更改为true?您的方法“MyQueryAndPend”的完成闭包从未被调用,因此完成闭包从未被触发
因此,在您的for声明之后:
for object in objectss {
//append the arrays
self.tableView.reloadData()
}
加:
触发关闭
我相信,一旦您解决了这个问题,一切都会很容易到位,因为您的check var将按照您的预期进行更新(也许您应该将其命名为类似isQuery的名称)
(旁注…不完全确定self.tableView.reloadData()
是否位于正确位置…)
不是。您多次调用reloadData
,对objects
中的每个对象调用一次。这是浪费。您应该这样写:
if let objectss = objects{
for object in objectss {
//append the arrays
}
self.tableView.reloadData()
}
另外,我不指望这段代码在主线程上运行,但您必须确保在主线程上调用了reloadData
if let objectss = objects{
for object in objectss {
//append the arrays
}
DispatchQueue.main.async {
self.tableView.reloadData()
}
}
最后,正如您已经被告知的,您无法调用自己的完成处理程序。请稍候。您还在完成处理程序中调用重新加载数据。因此,现在我们可以删除所有这些,只需调用完成处理程序即可:
if let objectss = objects{
for object in objectss {
//append the arrays
}
DispatchQueue.main.async {
completion()
}
}
现在,我们遇到了一个小小的困难,因为有两个案例需要考虑。如果<代码>如果失败了,我们仍然需要调用完成句柄,所以我们需要把调用移动到<代码>完成< /代码>,这样我们确信不管发生什么:
它都会发生。
if let objectss = objects{
for object in objectss {
//append the arrays
}
}
DispatchQueue.main.async {
completion()
}
有了最后的更改,我想代码将完成您希望它做的事情。感谢您的快速响应。我将completion()
直接放在结束之后?不用担心。不,您想放completion()在闭包内部,基本上是为了在收到查询闭包时触发完成闭包。是否需要在主线程中运行所有.reloadData()
无论何时你以任何方式、形状或形式触摸界面,你都必须处于主线程上。否则,小个子男人会在晚上来到你家偷你的内裤。而且,正如你正确地说的那样,checkerVar
内部的更改viewDidLoad
显然会在调用完成处理程序之前发生,所以请不要在如果你不了解它是如何工作的,你需要在“异步”上搜索。
if let objectss = objects{
for object in objectss {
//append the arrays
}
DispatchQueue.main.async {
completion()
}
}
if let objectss = objects{
for object in objectss {
//append the arrays
}
}
DispatchQueue.main.async {
completion()
}