我正在等待 Swift 中的 Parse 异步函数重新加载 UITableView
我不确定Completion Handler在这种情况下是否有用。或派遣异步。
我真的很困惑!有人可以帮忙解决这个问题吗?
var posts = [PFObject]()
for post in posts {
post.fetchInBackground()
}
tableView.reloadData() // I want to execute that when the async functions have finished execution
答案 0 :(得分:2)
你想使用fetchAllInBackground:块I在循环中启动一堆解析调用时会出现问题,这将导致返回所有这些调用所需的时间超过预期。 fetch documentation
看起来应该是这样的:
PFObject.fetchAllInBackground(posts, block: { (complete, error) in
if (error == nil && complete) {
self.tableView.reloadData()
}
})
需要注意的一点是,在您的示例中,帖子是空的,而且是一个通用的PFObject。我假设这仅仅是为了这个例子。否则,如果你想获得Parse中的所有帖子(而不是更新当前的帖子),你将需要使用PFQuery而不是获取。 query documentation
答案 1 :(得分:1)
您需要使用fetchInBackgroundWithBlock
。或者,如果您想等到所有已加载然后更新UI,请使用PFObject的+fetchAllInBackground:block:
。请注意,这是一个类方法,因此将被称为PFObject.fetchAllInBackground(...
。请参阅文档here。
无论哪种方式,因为您在后台线程中运行,您必须更新主线程上的UI。这通常使用dispatch_async
完成。
另外需要注意的是,如果在循环中运行fetchInBackgroundWithBlock
并在数组中收集所有结果,则数组不是线程安全的。您将不得不使用dispatch_barrier
或您自己的同步队列来同步对阵列的访问。第二个选项的代码如下:
// Declared once and shared by each call (set your own name)...
let queue = dispatch_queue_create("my.own.queue", nil)
// For each call...
dispatch_sync(queue) {
self.myArray.append(myElement)
}
答案 2 :(得分:1)
这是我为帮助协调异步流程而做的一个小课程:
class CompletionBlock
{
var completionCode:()->()
init?(_ execute:()->() )
{ completionCode = execute }
func deferred() {}
deinit
{ completionCode() }
}
诀窍是使用要在最后一个异步块之后执行的代码创建CompletionBlock的实例,并在闭包内部引用对象。
let reloadTable = CompletionBlock({ self.tableView.reloadData() })
var posts = [PFObject]()
for post in posts
{
post.fetchInBackground(){ reloadTable.deferred() }
}
对象将保持"活着"直到最后一次捕获超出范围。然后对象本身将超出范围,并且它的deinit将被调用,在那时执行你的终结代码。
答案 3 :(得分:0)
以下是使用fetchInBackgroundWithBlock
完成后重新加载tableView
的示例
var myArray = [String]()
func fetchData() {
let userQuery: PFQuery = PFUser.query()!
userQuery.findObjectsInBackgroundWithBlock({
(users, error) -> Void in
var userData = users!
if error == nil {
if userData.count >= 1 {
for i in 0...users!.count-1 {
self.myArray.append(userData[i].valueForKey("dataColumnInParse") as! String)
}
}
self.tableView.reloadData()
} else {
print(error)
}
})
}
我的示例是对用户类的查询,但您明白了......
答案 4 :(得分:0)
我已经对块进行了一些实验,它们似乎在主线程上被调用,这意味着可以在那里进行任何UI更改。我用来测试的代码看起来像这样:
func reloadPosts() {
PFObject.fetchAllIfNeededInBackground(posts) {
[unowned self] (result, error) in
if let err = error {
self.displayError(err)
}
self.tableView.reloadData()
}
}
如果您对是否在主线程上调用了块有疑问,可以使用NSThread
类来检查这个
print(NSThread.currentThread().isMainThread)
如果您希望它是防弹的,您可以将 reloadData
包裹在dispatch_block_t
内以确保它位于主线程上
编辑: 如果块在主线程上执行,则文档不会在任何地方声明,但source code非常清楚它是
+ (void)fetchAllIfNeededInBackground:(NSArray *)objects block:(PFArrayResultBlock)block {
[[self fetchAllIfNeededInBackground:objects] thenCallBackOnMainThreadAsync:block];
}