0

I have three separate calls to APIs. When all three calls are complete, I am going to aggregate the data and use it to form a separate model object.

I figured I would use property observers to accomplish this but I have no idea how it would be implemented. Any help or guidance would be appreciated.

I have created a model object for making the network calls that passes the response data into an escaping closure. This is the function where the data is parsed:

func loadLibrary() {

    //  League Data Containers

    var names = Dictionary<Int, String>() // API Call 1
    var titles = Dictionary<Int, String>() // Call 1
    var masteryLevels = Dictionary<Int, Int>() // 2
    var masteryPoints = Dictionary<Int, Int>() // 2

    //  Champion Data Containers

    var championRolesLibrary = Array<Dictionary<String,Array<Role>>>() // 3
    var championWithRoles = Dictionary<String,Array<Role>>() // 3
    var championRoles = Array<Role>() // 3

    //  Making Calls to the APIs

    leagueAPI.downloadStaticData { data in
        //  API Call is made and data is parsed into containers
    }

    leagueAPI.downloadChampionMasteryData { data in
        //  API Call is made and data is parsed into containers
    }

    championAPI.downloadChampionRolesData { data in
        //  API Call is made and data is parsed into containers
    }

    // Once all three calls have completed and the data has been parsed into different containers, the data is all brought together to create a library of objects.

    func aggregateData() {

        //  Take data from all the containers and use them in here.
        //  The issue is when to call this function.

    }
}
Tyler Travis
  • 117
  • 1
  • 5

1 Answers1

2

A simple way to solve that is by nesting all three requests:

func loadLibrary() {

    //  League Data Containers

    var names = Dictionary<Int, String>() // API Call 1
    var titles = Dictionary<Int, String>() // Call 1
    var masteryLevels = Dictionary<Int, Int>() // 2
    var masteryPoints = Dictionary<Int, Int>() // 2

    //  Champion Data Containers

    var championRolesLibrary = Array<Dictionary<String,Array<Role>>>() // 3
    var championWithRoles = Dictionary<String,Array<Role>>() // 3
    var championRoles = Array<Role>() // 3

    //  Making Calls to the APIs

    leagueAPI.downloadStaticData { data in
        //  API Call is made and data is parsed into containers

        leagueAPI.downloadChampionMasteryData { data2 in

            //  API Call is made and data is parsed into containers
            championAPI.downloadChampionRolesData { data3 in

                //  API Call is made and data is parsed into containers// Once all three calls have completed and the data has been parsed into different containers, the data is all brought together to create a library of objects.

                aggregateData() {

                //  Take data from all the containers and use them in here.
                //  The issue is when to call this function.

                }
            }
        }
    }

}

EDIT: You can also accomplish what you want by using DispatchGroup as said by @ rmaddy, in this case you would do this:

func loadLibrary() {

    //  League Data Containers

    var names = Dictionary<Int, String>() // API Call 1
    var titles = Dictionary<Int, String>() // Call 1
    var masteryLevels = Dictionary<Int, Int>() // 2
    var masteryPoints = Dictionary<Int, Int>() // 2

    //  Champion Data Containers

    var championRolesLibrary = Array<Dictionary<String,Array<Role>>>() // 3
    var championWithRoles = Dictionary<String,Array<Role>>() // 3
    var championRoles = Array<Role>() // 3

    // Create DispatchGroup
    let dispatchGroup = DispatchGroup()

    //  Making Calls to the APIs

    dispatchGroup.enter()
    leagueAPI.downloadStaticData { data in
        //  API Call is made and data is parsed into containers
        dispatchGroup.leave()
    }

    dispatchGroup.enter()
    leagueAPI.downloadChampionMasteryData { data in
        //  API Call is made and data is parsed into containers
        dispatchGroup.leave()
    }
    dispatchGroup.enter()
    championAPI.downloadChampionRolesData { data in
        //  API Call is made and data is parsed into containers
        dispatchGroup.leave()
    }

    // Once all three calls have completed and the data has been parsed into different containers, the data is all brought together to create a library of objects.
    dispatchGroup.notify(queue: DispatchQueue.global(qos: .background)){
        aggregateData() {

            //  Take data from all the containers and use them in here.
            //  The issue is when to call this function.

        }
    }

}
Alexandre Lara
  • 2,464
  • 1
  • 28
  • 35
  • Great answer. One thing, though. Did you mean to make func aggregateData a local function of the `DispatchGroup` notify closure? I'm guessing that you meant to **CALL** the function rather than declare it. – Duncan C Apr 28 '17 at 23:46
  • @DuncanC You're right, I had just copy & paste from the question and I missed that, but now I edited my answer. Thank you! – Alexandre Lara Apr 28 '17 at 23:51