等待一个块加载,然后再加载更多
Posted
技术标签:
【中文标题】等待一个块加载,然后再加载更多【英文标题】:Waiting for a chunk to load, before loading more 【发布时间】:2017-03-10 21:34:19 【问题描述】:我正在构建一个应用程序,我需要在其中加载数据块,我的意思是先加载 5 个项目,然后再继续加载另外 5 个项目,但我不知道该怎么做。目前我将我的项目列表分块,所以我得到一个列表列表,每个列表有 5 个项目。现在 for 循环只是触发请求,但我想等待响应,然后继续 for 循环。
我用的是alamofire,我的代码是这样的。
private func requestItemsForField(items: [Item], completion: @escaping (_ measurements: Array<Measurement>?, _ success: Bool) -> ())
let userPackageId = UserManager.instance.selectedUserPackage.id
let params = ["userPackageId": userPackageId]
for field in fields
let url = apiURL + "images/\(field.id)"
let queue = DispatchQueue(label: "com.response-queue", qos: .utility, attributes: [.concurrent])
Alamofire.request(url, method: .get, parameters: params, headers: headers()).responseArray(queue: queue, completionHandler: (response: DataResponse<[Item]>) in
if let items = response.result.value as [Item]?
NotificationCenter.default.post(name: NSNotification.Name(rawValue: "itemsLoadedNotification"), object: nil)
completion(items, true)
else
print("Request failed with error: \(response.result.error)")
completion(nil, false)
)
这是我将列表分块并将其传递给上面的地方。
private func fetchAllMeasurements(completion: @escaping (_ measurements: [Item]?, _ done: Bool) -> ())
let fieldSet = FieldStore.instance.data.keys
var fieldKeys = [Item]()
for field in fieldSet
fieldKeys.append(field)
// Create chunks of fields to load
let fieldChunks = fieldKeys.chunkify(by: 5)
var measurementsAll = [Measurement]()
for fields in fieldChunks
requestItemsForField(fields: fields, completion: (measurements, success) in
if let currentMeasurement = measurements
measurementsAll.append(contentsOf: currentMeasurement)
completion(measurementsAll, true)
)
【问题讨论】:
我相信你需要在前端实现类似分页的东西。我建议您更新后端以进行分页,但是如果您需要在前端实现它,请检查此链接 -> PagedArray 你可以尝试使用dispatch_group或者dispatch_barrier 【参考方案1】:您需要根据您的请求获取您将拥有的测量数量(例如服务器有 34 个测量),然后编写类似的代码
var serverMeasurementsCount = 1 //should be for first request
func requestData()
if self.measurements.count < self.serverMeasurementsCount
...requestdata data in
self.serverMeasurementsCount = data["serverMeasurementsCount"]
self.measurements.append(..yourData)
self.requestData()
或者打电话给requestData
不在completion handler
或其他地方
编辑:固定代码(serverMeasurementsCount = 1
)
【讨论】:
【参考方案2】:听起来你需要做一些类似var index = 0
的事情,而不是使用for循环,然后调用requestItemsForField()
发送fieldChunks[index]
作为第一个参数。然后在完成处理程序中,检查是否有另一个数组元素,如果有,则再次调用requestItemsForField()
,这次将fieldChunks[index+1]
作为第一个参数发送。
【讨论】:
但是如果我再次调用 requestItemsForField() ,我们将在其中添加另一个完成处理程序? 如果我的想法可行,你就不需要编写另一个完成处理程序,因为每个完成处理程序都会产生另一个对requestItemsForField()
的调用,并且该调用当然也会运行它自己的完成处理程序它完成了。等。当您到达数组的末尾时,它将停止产生调用,因为完成处理程序中的代码只会在至少还有一个数组元素剩余时才会产生新的调用。总体效果是,每次对requestItemsForField()
的新调用都不会在上一次调用完成之前发生,这是您最初的目标。
更清楚地说,每次requestItemsForField()
到达其完成处理程序时,都会再次调用requestItemsForField()
。这就是为什么只需要编写一个完成处理程序的原因。而且它不会永远持续下去,因为完成处理程序中的代码只会在还有另一个数组元素要处理时才调用该函数。【参考方案3】:
一种解决方案是创建一个新的递归函数来填充项目,在闭包中添加一个新的 Bool 参数作为 isComplete。然后在 isComplete 布尔值完成时调用该函数。要打破递归函数,添加itemsCountMax的全局静态变量,如果itemCountMax == itemsCount 打破递归函数。
【讨论】:
以上是关于等待一个块加载,然后再加载更多的主要内容,如果未能解决你的问题,请参考以下文章