我有一个重新加载数据的应用程序(通过运行两个查询,将查询的信息附加到数组,以及重新加载tableview数据)。两个查询都设置为在viewDidLoad()
上运行的函数,但也链接到刷新函数(用户可以通过拉动刷新来手动激活)。查询工作正常,但是viewDidLoad()
正在运行(但尚未完成)查询函数时偶尔会出现问题,并且用户在完成之前尝试进行刷新...重复项添加到数组,我想避免这一点。我的想法是最初将检查变量设置为false,在 viewDidLoad()完成后将其更改为true ,并且仅在变量更改为变量后才允许pull to refresh功能工作真正。这是功能的设置:
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():
var checkerVar = false
override func viewDidLoad() {
super.viewDidLoad()
print("It loaded")
myQueryandAppend(completion: {
self.tableView.reloadData()
print("myQuery was called in viewDidLoad()")//never called
checkerVar = true
})
refreshControl = UIRefreshControl()
refreshControl.attributedTitle = NSAttributedString(string: "Pull to refresh")
refreshControl.addTarget(self, action: #selector(MainPageVC.refresh(_:)), for: UIControlEvents.valueChanged)
tableView.addSubview(refreshControl)
self.navigationController?.navigationBar.isHidden = true
checkerVar = true //isn't changed on *completion* of the function
}
然后是刷新处理程序:
func refresh(_ sender: AnyObject){
if checkerVar == true{
myQueryandAppend(completion: {
self.tableView.reloadData()
self.refreshControl.endRefreshing()
})
self.refreshControl.endRefreshing()
}else{
self.refreshControl.endRefreshing()
}
}
问题是,使用checkerVar,从不调用viewDidLoad()闭包中完成内的实例(上面的print语句永远不会被记录),我相信viewDidLoad()底部的第二个实例立即完成,而不是实际等待功能完成。此外,任何(completion:{})
内的打印语句都不会被记录。
所以:1。为什么未完成完成中的打印语句(更重要的是)2。如何在 viewDidLoad()
完成后将checkerVar更改为true ?
答案 0 :(得分:1)
你的方法" myQueryandAppend"的完成闭包从未被调用,因此完成闭包永远不会被解雇。
所以在你的陈述之后:
for object in objectss {
//append the arrays
self.tableView.reloadData()
}
添加:
completion()
触发关闭。
我相信一旦你解决了这个问题,一切都会很容易到位,因为你的check var会像你期望的那样更新(也许你应该把它命名为isQuerying。
答案 1 :(得分:1)
(旁注......不完全确定
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()
}
}
最后,正如您已经被告知的那样,您未能调用自己的completion
处理程序。可是等等。您还在reloadData
处理程序中调用completion
。现在我们可以删除所有内容,只需拨打completion
:
if let objectss = objects{
for object in objectss {
//append the arrays
}
DispatchQueue.main.async {
completion()
}
}
然而,现在我们遇到了一些困难,因为有两种情况需要考虑。如果if let
失败怎么办?我们仍然需要调用完成处理程序,因此我们需要将调用移至completion
,以便我们确定无论如何都会发生:
if let objectss = objects{
for object in objectss {
//append the arrays
}
}
DispatchQueue.main.async {
completion()
}
随着最后的改变,我认为代码将完成您希望它做的事情。