简体   繁体   中英

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, eg 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()
    }
}

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()
    }
    // ...
}

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