Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Waiting for a chunk to load, before loading more

I'm building an app, where I need to load data in chunks, I mean first load 5 items and then proceed with another 5, but I can't figure out how to do that. At the moment I chunk up my list of items, so I get a list of lists with 5 items in each. Right now the for-loop just fires away with requests, but I want to wait for the response and then proceed in the for loop.

I use alamofire, and my code looks like this.

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)
        }
    })
    }
}

This is where i chunk up my list, and pass it to the above.

 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)
            }
        })
    }
}
like image 477
Recusiwe Avatar asked Mar 10 '17 21:03

Recusiwe


2 Answers

you need to get number of measurements you will have (for example server has 34 measurements) with your request and then code something like

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()
        }
    }

or call requestData not inside completion handler or somewhere else

edit: fixed code a bit (serverMeasurementsCount = 1)

like image 192
JuicyFruit Avatar answered Nov 08 '22 23:11

JuicyFruit


Instead of using a for loop, it sounds like you need do something like var index = 0 to start with, and call requestItemsForField() sending in fieldChunks[index] as the first parameter. Then in the completion handler, check to see whether there's another array element, and if so, call requestItemsForField() again, this time sending in fieldChunks[index+1] as the first parameter.

like image 27
ClayJ Avatar answered Nov 09 '22 00:11

ClayJ