swifturlsession

How to handle two completion handlers in one function swift


func fetch(completionHandler: @escaping ([OnSaleItem], [SlideItem], [NewArrivalItem], [EditorChoiceItem], Error?) -> Void) {
        apiCaller.fetchUser(completionHandler: { baseData, error in
            if let baseData = baseData {
                self.apiCaller.fetchSlideOnSaleEditorChoiceNewArrivalData(baseData: baseData, completionHandler: { [self] decodedString, error in
                    if let decodedString = decodedString {
                        
                        let data = convertToDictionary(text: decodedString)
                        let onSaleProductResponse = data["onsale"] as! NSArray
                        let slideResponse = data["slide"] as! NSArray
                        let newArrivalResponse = data["newarrival"] as! NSArray
                        let editorChoiceResponse = data["featured"] as! NSArray
                        var onSaleProducts : [Any] = []
                        var slide : [Any] = []
                        var newArrivalProducts : [Any] = []
                        var editorChoiceProducts : [Any] = []
                        
                        for item in onSaleProductResponse {
                            onSaleProducts.append(item as! Dictionary<String,String>)
                        }
                        for data in onSaleProducts {
                            onSaleItems.append(OnSaleItem(dict: data as! [String : String]))
                        }
                        
                        for item in slideResponse {
                            slide.append(item as! Dictionary<String,String>)
                        }
                        for data in slide {
                            slideItems.append(SlideItem(dict: data as! [String : String]))
                        }
                        
                        for item in newArrivalResponse {
                            newArrivalProducts.append(item as! Dictionary<String,String>)
                        }
                        for data in newArrivalProducts {
                            newArrivalItems.append(NewArrivalItem(dict: data as! [String : String]))
                        }
                        
                        for item in editorChoiceResponse {
                            editorChoiceProducts.append(item as! Dictionary<String,String>)
                        }
                        for data in editorChoiceProducts {
                            editorChoiceItems.append(EditorChoiceItem(dict: data as! [String : String]))
                        }
                        
                        completionHandler(onSaleItems, slideItems, newArrivalItems, editorChoiceItems, nil)
                    }
                })
                self.apiCaller.fetchProducts(baseData: baseData, completionHandler: { [self] dataProducts, error in
                    if let dataProducts = dataProducts {
                        let data = convertToDictionary(text: dataProducts)
                        let productResponse = data["data"] as! NSArray
                        var products : [Any] = []
                        
                        for item in productResponse {
                            products.append(item as! Dictionary<String,String>)
                        }
                        for data in products {
                            daftarProdukItems.append(DaftarProdukItem(dict: data as! [String : String]))
                        }
                        //this line is the problem
                        completionHandler(daftarProdukItems, nil)
                    }
                })
            }
        })
    }

I have a problem when I need to return using completion handlers but I request from 2 API Endpoints.

The first endpoint is fetchSlideOnSale...

The second endpoint is fetchProducts

Additional information: when I need to fetch first or second endpoints I need baseData first

I can't return completionhandlers like the code below. the line code problem returns this error

Cannot convert value of type '[DaftarProdukItem]' to expected argument type '[OnSaleItem]'


Solution

  • Check the code below for DispatchGroup solution.

    apiCaller.fetchUser { data, error in
        let group = DispatchGroup()
        
        group.enter()
        self.apiCaller.fetchProducts(baseData: data) { _, _ in
            //Do something like decoding data
            group.leave()
        }
        
        group.enter()
        self.apiCaller.fetchSlideOnSaleEditorChoiceNewArrivalData(baseData: data) { _, _ in
            //Do something like decoding data
            group.leave()
        }
        
        group.notify(queue: .main) {
            //Group data if needed then completion
            //completionHandler...
        }
    }