iOS Concurrency with GCD and Operations - Part 4: | Ray Wenderlich

Learn how use GCD dispatch groups so that you can respond to the completion of a collection of GCD tasks.


This is a companion discussion topic for the original entry at https://www.raywenderlich.com/3648-ios-concurrency-with-gcd-and-operations/lessons/4

how are the tasks run under print(“=== Group of sync tasks ===\n”) this statement synchronous?
We are using workerQueue’s(which is a concurrent queue) async call to call slowAdd((Int, Int))

hi ruban: you’re right! It’s a typo, or copy-paste error. Thanks!

Hi, Audrey, I’ve tried another way to realize the challenge, but it didn’t work as expected. Here’s my code.

DispatchQueue.main.async(group: animationGroup) {
	UIView.animate(withDuration: 1, animations: {
  box.center = CGPoint(x: 150, y: 150)
	}, completion: {
		_ in
		DispatchQueue.main.async(group: animationGroup) {
			UIView.animate(withDuration: 2, animations: {
				box.transform = CGAffineTransform(rotationAngle: .pi/4)
			}, completion: .none)
		}
	})
}

DispatchQueue.main.async(group: animationGroup){
	UIView.animate(withDuration: 4, animations: { () -> Void in
		view.backgroundColor = UIColor.blue
	})
}
animationGroup.notify(queue: DispatchQueue.main) {
  print("Animations Completed!")
}

Is there anything wrong that I failed to get notified after all animations complete? Could you please help? Thanks.

running your code, the Animations completed message appears too soon, because the animate tasks appear to finish immediately (you dispatched them asynchronously, so they return immediately).

To make the group wait for the task to really finish, you need to specify when the task enters and leaves the group: enter before the animations, and leave in the completion handler. The code below works the same as the finished challenge playground:

let animationGroup = DispatchGroup()
PlaygroundPage.current.liveView = view

UIView.animate(withDuration: 1, animations: {
  animationGroup.enter()
  box.center = CGPoint(x: 150, y: 150)
}, completion: { _ in
  UIView.animate(withDuration: 2, animations: {
    animationGroup.enter()
    box.transform = CGAffineTransform(rotationAngle: .pi/4)
  }, completion: { _ in
    animationGroup.leave()
  })
  animationGroup.leave()
})

UIView.animate(withDuration: 4, animations: {
  animationGroup.enter()
  view.backgroundColor = UIColor.blue
}, completion: { _ in
  animationGroup.leave()
})

animationGroup.notify(queue: DispatchQueue.main) {
  print("Animations Completed!")
}

the solution in the playground is cleaner, because the enter/leave calls are embedded in the extended animate method

Thanks so much for you applying. Really, I misunderstood the async(group:) function. Its duty is just dispatching block specific groups, but not include when the block is executed. That’s why we need group.enter/leave to control the exact time, right?

And of course, it’s not necessary to dispatch it asynchronous since the animation API is already asynchronous. Adding them again is pointless…

you got it!

The purpose of GCD and OperationQueue is to make synchronous tasks behave asynchronously. But there are features we want to use with APIs that are already asynchronous, so we need a way to tell the system when they really finish.

Love your courses, especially video ones. They do mean a lot to me and fix up many of my misunderstandings. :hugs:

1 Like

The video for this tutorial isn’t working …

hi! it’s working for me — what’s happening for you?

Thank you for this neat tutorial!

1 Like

@akashlal Please check out the updated version of the course when you get a chance:

https://www.raywenderlich.com/9461083-ios-concurrency-with-gcd-and-operations

I hope it helps!

1 Like