Edward Hasted
Edward Hasted

Reputation: 3433

Swift - Dispatch Queues and the U/I running serially

I have a secondary LaunchScreenViewController for an App that has some animation whilst it gathers three types of background data.

Everything works but the order in which the DispatchQueues.async are run is random. However if I change them to DispatchQueues.sync everything happens in the right order but runs so fast (even with sleeps) you don't see the animations.

This needs to be .sync but how do I control the U/I so that I can see the animation? (Shown here as, e.g. self.subLogo1View.isHidden = true)

Here's the code:

// Queuing Variables    
var semaphore    = DispatchSemaphore(value: 1)    
var semaphoreSub = DispatchSemaphore(value: 1)

override func viewDidLoad() {
    super.viewDidLoad()
    DispatchQueue.global().async {
        self.semaphore.wait()
        self.gatherData()
        self.semaphore.signal()
    }

    DispatchQueue.global().async {
        self.semaphore.wait()
        self.checkNetworkAvailability()
        self.semaphore.signal()
    }

    DispatchQueue.global().async {
        self.semaphore.wait()
        self.checkSomething()
        self.semaphore.signal()
    }   
}


func gatherData() {
    DispatchQueue.main.async {
        self.semaphoreSub.wait()
        print ("1")
        self.subLogo1View.isHidden = true
        self.subLogo1View.setNeedsDisplay()
        self.semaphoreSub.signal()
    }
}

func checkNetworkAvailability() {
    DispatchQueue.main.async {
        self.semaphoreSub.wait()
        print ("2")
        self.subLogo2View.isHidden = true
        self.subLogo2View.setNeedsDisplay()    
        self.semaphoreSub.signal()
    }
}

func checkSomething() {
    DispatchQueue.main.async {
        self.semaphoreSub.wait()
        print ("3")
        self.subLogo3View.isHidden = true
        self.subLogo3View.setNeedsDisplay()
        self.semaphoreSub.signal()
    }
}

Upvotes: 0

Views: 265

Answers (1)

Andreas Oetjen
Andreas Oetjen

Reputation: 10199

Instead of manually serializing your closures with a bunch of semaphores, you maybe better use a custom serial queue. For animation, user UIView.animate

Something like this:

func gatherData() {
    DispatchQueue.main.async {  // or sync, depending on your animation needs
        print ("1: gather Data")
        UIView.animate(withDuration: 0.5) { 
            self.subLogo1View.alpha = 0  // instead of isHidden
        }
    }
}

func viewDidLoad() {
    var mySerialQueue = DispatchQueue (label:"my.serial")
    mySerialQueue.async {
        self.gatherData()
    }
    mySerialQueue.async {
        self.checkNetworkAvailability()
    }
    // ...
}

Upvotes: 1

Related Questions