简体   繁体   中英

How to use DispatchGroup to update UI only after for-in loop has completed

When a user taps a button, that triggers a lengthy function consisting of an API call and calculations.

@IBAction func buttonTapped(_ sender: Any) {
        
        var itemIndex = 0
        let dispatchGroup = DispatchGroup()
        
        for name in (entireRecipe?.extendedIngredients!)! {
            
            dispatchGroup.enter()
            
            CalculatorService().calculate() { item   in
                self.arrayItem.append(item)
                self.totalItems = self.arrayItems.reduce(0, +)
            }
            itemIndex = itemIndex + 1
        }
        dispatchGroup.leave()
        
        dispatchGroup.notify(queue: .main) {
            print("DispatchGroup Notified")
            self.itemLabel.text = "\(self.totalItems)"
        }
    }

My rationale on the above is that:

  1. dispatchGroup is entered when the for-in loop starts
  2. dispatchGroup is left after the for-in loop has iterated through the entire array
  3. dispatchGroup is only then notified, and the UI label is updated

However, it looks like dispatchGroup.notify is not being run when intended, and so the UI label is not being updated after the for-in loop is complete.

Is there anything missing from my dispatchGroup code? Any help is much appreciated!

The leave line must be inside the closure

for name in (entireRecipe?.extendedIngredients!)! {
    
    dispatchGroup.enter()
    
    CalculatorService().calculate() { item   in
        self.arrayItem.append(item)
        self.totalItems = self.arrayItems.reduce(0, +)
        dispatchGroup.leave()
    }
    itemIndex = itemIndex + 1
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM