How Do We Implement Wait/Notify in Swift

Waiting until the task finishes

Use DispatchGroups to achieve this. You can either get notified when the group's enter() and leave() calls are balanced:

func myFunction() {
var a: Int?

let group = DispatchGroup()
group.enter()

DispatchQueue.main.async {
a = 1
group.leave()
}

// does not wait. But the code in notify() is executed
// after enter() and leave() calls are balanced

group.notify(queue: .main) {
print(a)
}
}

or you can wait:

func myFunction() {
var a: Int?

let group = DispatchGroup()
group.enter()

// avoid deadlocks by not using .main queue here
DispatchQueue.global(attributes: .qosDefault).async {
a = 1
group.leave()
}

// wait ...
group.wait()

print(a) // you could also `return a` here
}

Note: group.wait() blocks the current queue (probably the main queue in your case), so you have to dispatch.async on another queue (like in the above sample code) to avoid a deadlock.

Wait and notify equivalent in Objective c?

There are numerous techniques you could use. You can use NSCondition or POSIX semaphores or dispatch semaphores or by using run loops. Check out the Concurrency Guide and the the Threading Guide.

My personal favourite at the moment is the dispatch semaphore.

Swift wait for closure thread to finish

Simplest way to wait for an async task is to use a semaphore:

let semaphore = DispatchSemaphore(value: 0)

doSomethingAsync {
semaphore.signal()
}

semaphore.wait()

// your code will not get here until the async task completes

Alternatively, if you're waiting for multiple tasks, you can use a dispatch group:

let group = DispatchGroup()

group.enter()
doAsyncTask1 {
group.leave()
}

group.enter()
doAsyncTask2 {
group.leave()
}

group.wait()

// You won't get here until all your tasks are done

Wait for async code to finish Swift

If you do not need to be able to 'read' from the identifier which notification it is, you could used a randomized string as identifier instead.

Even if it is possible to properly generate a unique id like you do now you should not rely on the control flow for correct id generation. This is generally considered bad coding practice, especially when relying on (3th) party libraries or API's. One change could break it.

You could generate randomized strings as described here. Using a alphanumeric string of 24 characters gives (36+36+10)^24 combinations, making the chance of a collision negligable.

You can use the userinfo dictionary or some other means of persistence to associate the identifiers with specific notifications. If you are using CoreData you can associate notification objects, with unique identifiers, to medicineRequests.

DispatchGroup notify() called immediately - not waiting for Enter/Leave

As @pkamb pointed out in the comments the problem was that I was trying to fire the dispatchGroup.notify() inside the init() method.

At that time of the execution, as I didn't call requestBanners() yet, the DispatchGroup counter was equal to zero and that led to a an early call to the delegate?.setUpCollection() with an empty array.

Moving the dispatchGroup.notify() block at the end of the requestBanners() method solved the problem :)



Related Topics



Leave a reply



Submit