使用DispatchGroup或一些并发结构按顺序加载数据并在UITableViewController中填充单元格 [英] Using `DispatchGroup` or some concurency construct to load data and populate cells in `UITableViewController` sequentially
问题描述
我使用的是Swift 4和Xcode 11.4
I am on swift 4 and xcode 11.4
该应用程序正在加载一个可能包含100或1000项商品的Feed,比如说500项商品.使用Amplify
的GraphQL
查询将一次抓取500个项目,然后每个项目将加载其他数据.数据将填充UITableViewController
中的单元格.理想情况下,此过程将按以下确切顺序进行:
The app is loading a feed with potentially 100s or 1000s of items, let's say 500 items. The 500 items will be grabbed once using Amplify
's GraphQL
query, then each item will then load additional data. The data will populate the cells in a UITableViewController
. Ideally this process would happen in the following exact sequence:
-
query
500个项目 - cell_1加载其他数据.
- cell_1呈现数据并显示在
UITableViewController
中
- cell_2加载其他数据.
- cell_2渲染数据并显示在
UITableViewController
中
query
500 items- cell_1 load additional data.
- cell_1 render data and display in
UITableViewController
- cell_2 load additional data.
- cell_2 render data and display in
UITableViewController
...
- cell_500加载其他数据
- cell_500渲染数据并显示在
UITableViewController
中
因此,用户将看到瀑布". Feed中呈现的单元数.
So the user will see a "waterfall" of cells being rendered in the feed.
这似乎是一个用例,需要对执行进行更好的控制,这将需要以下操作: https://developer.apple.com/documentation/dispatch/dispatchgroup
This seems like a use case that require some finer control of execution, which would need this: https://developer.apple.com/documentation/dispatch/dispatchgroup
我是Swift的新手,所以对我来说有点高级.提供了用于GraphQL
查询的存根,用于加载其他数据的类函数以及顶层UITableViewController
.请说明如何使用DispatchGroup
.
I am new to Swift so this is a bit advanced for me. Provided is the stub for GraphQL
query, and class function that loads additional data, and the top level UITableViewController
. Please instruct how I would use DispatchGroup
.
class Feed: UITableViewController {
var dataSource: [FullItem] = []
override func viewDidLoad(){
super.viewDidLoad()
queryItem{ items
for item in items {
let itemInstanceWithMoreData = FullItem( id: item.id )
itemInstanceWithMoreData.loadFullData()
}
}
}
}
func queryItems( callBack: @escaping ([Item]) -> Void ){
_ = Amplify.API.query(from: Item.self, where: predicate) { (event) in
switch event {
case .completed(let result):
switch result {
case .success(let xs):
callBack(xs)
case .failure:
break
}
case .failed:
break
default:
break
}
}
}
class FullItem {
id: String
name: String?
init( id ){ self.id = id; self.name = "" }
func loadData(){
let _ = Amplify.API.query(from: FullItem.self, byId: self.id) { (event) in
switch event {
case .completed(let res):
switch res{
case .success (let musr):
if (musr != nil){
self.name = musr!.name
} else {
break
}
default:
break
}
default:
print("failed")
}
}
}
}
附录
如果我要的顺序不可行,我还将满足query
500个项目的要求,为每个项目提供load
附加数据,然后渲染单元格.但是无论哪种方式,单元格都不应使用空数据进行渲染.
addendum
If the sequence I am asking is not possible, I would also settle for query
500 items, load
additional data for each one, then rendering the cells. But either way, the cell should not render with empty data.
推荐答案
您的示例不完整,无法编译,因此是简短版本
Your example is incomplete and doesn't compile so this is the short version
声明loadData()
func loadData(completion: @escaping () -> Void) {
,并确保在任何情况下都调用completion()
(这很关键!)
and make sure that completion()
is called in any case (this is crucial!) for example
default:
completion()
print("failed")
要正确使用DispatchGroup
,必须在调用异步任务之前在循环中调用enter
内部,并在任务的完成处理程序中调用leave
.在外部末尾,循环实现notify
To use DispatchGroup
properly you have to call enter
inside the loop before calling the asynchronous task and call leave
in the completion handler of the task. At the end outside the loop implement notify
override func viewDidLoad(){
super.viewDidLoad()
let group = DispatchGroup()
queryItems { items
for item in items {
group.enter()
let itemInstanceWithMoreData = FullItem( id: item.id )
itemInstanceWithMoreData.loadData {
group.leave()
}
}
group.notify(queue: .main) {
self.tableView.reloadData()
}
}
}
要按顺序顺序插入和更新项目,您需要一个异步Operation
和一个串行OperationQueue
. DispatchGroup
不保留订单.
To insert and update the items serially in order you need an asynchronous Operation
and a serial OperationQueue
. DispatchGroup
doesn't preserve the order.
这篇关于使用DispatchGroup或一些并发结构按顺序加载数据并在UITableViewController中填充单元格的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!