Josh
Josh

Reputation: 9

Update app icon badge number after fetching count value from API

I want to update app icon badge number by totalling all badge counts. Following is my function. The problem is that count goes out of sync since I'm fetching the count values from APIs and closures make it out of sync. updateBadgeCounts() will be called many times during app usage.

How do I make it work?

extension UIViewController {

    func updateBadgeCounts() {
        fetchValue1() { (result, error) in
            UIApplication.shared.applicationIconBadgeNumber = result!.data!.count!
        }

        fetchValue2() { (result, error) in
           UIApplication.shared.applicationIconBadgeNumber += result!.data!.count!
        }
    }

}

Calling above func

class MainTabBarController: UITabBarController, UITabBarControllerDelegate {

    override func viewDidLoad() {

        // Do other stuff...

        DispatchQueue.main.async() {
            self.updateBadges()
        }

    }

    override func tabBar(_ tabBar: UITabBar, didSelect item: UITabBarItem) {
        DispatchQueue.main.async() {
            self.updateBadges()
        }
    }

}

Upvotes: 0

Views: 352

Answers (2)

Palmer
Palmer

Reputation: 21

If you haven't figured it out yet then here is one solution. You can implement it in nested functions. Something like this

func updateValues() {
    fetchValue1() { (result, error) in
        fetchValue2() { (result, error) in
            // update all badges numbers here
        }
    }
}

Upvotes: 1

Chris
Chris

Reputation: 4411

The two values are fetched by separate asynchronous calls, so they will return at different times.

You could store the two values in view controller variables and use didSet to update the badge.

var value1: Int = 0 {
    didSet {
        updateBadge()
    }
}

var value2: Int = 0 {
    didSet {
        updateBadge()
    }
}

func updateBadge() {
    UIApplication.shared.applicationIconBadgeNumber = value1 + value2
}

func updateValues() {
    fetchValue1() { (result, error) in
        if let result = result {
            self.value1 = result.data!.count
        }
    }
    fetchValue2() { (result, error) in
        if let result = result {
            self.value2 = result.data!.count
        }
    }
}

On a separate note, I have added optional binding to check result is not nil. Depending on your data, you may need to handle it differently. For example, you might need to cast your result.data to a specific type.

Upvotes: 1

Related Questions