我有一个重新加载数据的应用程序(通过运行两个查询,将查询信息附加到数组中,以及重新加载表视图数据)。这两个查询都被设置为在viewDidLoad()上运行的函数,但也链接到一个刷新函数(用户可以手动启动该函数,并进行拉到刷新)。但是,当viewDidLoad()运行查询函数(但尚未完成)时,查询工作正常,偶尔会出现一个问题,用户试图在它完成之前拉出刷新.重复项被添加到数组中,我想避免这种情况。我的想法是最初将一个检查变量设置为false,在viewDidLoad()完成后将其更改为true,并且只允许在变量被更改为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():
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()闭包中的补全中的实例从未被调用(它上面的打印语句从未被记录过),而且我认为viewDidLoad()底部的第二个实例是立即完成的,而实际上没有等待函数完成。此外,在任何(completion:{})中都不会记录任何print语句。所以: 1.为什么没有调用完成中的print语句?(更重要的是) 2.如何使checkerVar只在viewDidLoad()完成后才被更改为true?
发布于 2017-01-17 23:47:28
(旁注.不完全确定
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()
}经过最后的修改,我认为代码会做你想做的事情。
发布于 2017-01-17 23:45:44
您的方法“myQueryandAppend”的完成闭包从未被调用,因此完成闭包从未触发。
所以在你的陈述之后:
for object in objectss {
//append the arrays
self.tableView.reloadData()
}加:
completion()来触发关闭。
我相信,一旦您修复了这个问题,一切都会很容易到位,因为您的check将按您的预期进行更新(也许您应该将它命名为类似于isQuerying的名称)。
https://stackoverflow.com/questions/41708946
复制相似问题