Search code examples
iosswiftxcodealamofirensdata

How to make multiple network requests one by one so I don't lose data?


I have the following scenario - I have an app that needs to get some audio files from the server in background and asynchronously. The audio files are a big number - like 10000. They are 1-2 sec mp3 files (like 5-10 kb each). For each of these files I have to make a network request and get the files using its ID. There are two types of audio files - for your native language and for your learning language. So I go through all the IDs like this - 1. get me native audio with ID 1, then get me learning audio with ID 1 ---> ID+1 and again the same scenario.

The problem is that when I go like this, some of the audio files are corrupted at the end. I guess it's because I am not doing the async requests properly. Here is my code:

DispatchQueue.global(qos: .background).async {
let myGroup = DispatchGroup()

for category in arrCategories {
    for library in category.libraries {
        for group in library.groups {
            for word in group.words {

                myGroup.enter()

                User.current.getAudioFile(forWord: word, language: User.current.nativeLanguage, isNative: true, callback: { (success) in
                    if success {
                        User.current.getAudioFile(forWord: word, language: User.current.learningLanguage, isNative: false, callback: { (success) in
                            if success {
                                myGroup.leave()
                            } else {
                                print("ERROR LEARNING")
                                myGroup.leave()
                            }
                        })
                    } else {
                        print("ERROR NATIVE")
                        myGroup.leave()
                    }
                })
            }
        }
    }
}

myGroup.notify(queue: DispatchQueue.main, execute: {
    print("READY")
    running = false
})

And my network request:

        request(urlRequest).response { (response) in

            if response.data != nil && response.error == nil {
                let soundData = response.data! as NSData
                let fileURL = URL(fileURLWithPath: filePath)

                do {
                    try soundData.write(to: fileURL, options: .atomic)
                    callback(true)
                } catch {
                    print(error)
                    callback(false)
                }
            } else {
                print(response.error?.localizedDescription)
                callback(false)
            }

Can anybody tell me what's wrong with the code? Because some audio files are not playing if I use this approach. But if I download only this file without making so many requests, it plays normally.


Solution

  • Using a loop just starts all the async requests. Your problem lies in handling all the parallel responses.

    One option is to use a mutex/semaphor to block the loop before finishing the first one (I wouldn't advice it.

    The second option would be creating a list of request and whenever a request finishes start the next one.