Reputation: 87
this is a hard one to explain. I am creating a serial queue for handling some work in my app. Imagine that i do something like this:
dispatch_async(myQueue, { () -> Void in
self.SendSMS();
});
dispatch_async(myQueue, { () -> Void in
self.SendEmail();
});
Now what i would like to do is to only call the self.SendEmail after a delegate(SendSMS delegate) finishes its work.
Is there a simple way to do this?
Many thanks
Upvotes: 1
Views: 1775
Reputation: 12687
Yes, you can do it, in next steps:
// create tasks group handle
let taskGroup = dispatch_group_create()
let mainQueue = dispatch_get_main_queue()
// write your blocks in needed order
dispatch_group_async(taskGroup, mainQueue) { [weak self] in
// execute your code
// don't forget to use self with optional, i.e.: self!.property or function
self!.SendSMS()
}
dispatch_group_async(taskGroup, mainQueue) { [weak self] in
self!.SendEmail()
}
// and of course you need to catch completion of this task group
dispatch_group_notify(taskGroup, mainQueue) {
println("All work is done, milord!")
}
UPD. The solution above is about asynchronous execution without order, as named and one of two can be completed earlier than declared order. You need to use dependencies as solution of continuously execution. I'm talking about ordering in multithreading, not about completion closures or executor pattern. Notice, that there're more than one case to do this. One of them – below:
let queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)
dispatch_async(queue) {
dispatch_sync(queue) {[weak self] in
self?.SendSMS()
}
dispatch_sync(queue) {[weak self] in
self?.SendEmail()
// here you need to call your completion of success function in main thread
}
}
Be aware, that code in your functions must exists in the same queue and use synchronous method for server requests. But this is another story ;)
Upvotes: -1
Reputation: 437947
Assuming that SendSMS
is an asynchronous method, I'd advise changing SendSMS
to take a completion handler closure:
// define property to hold closure
var smsCompletionHandler: (()->())?
// when you initiate the process, squirrel away the completion handler
func sendSMSWithCompletion(completion: (()->())?) {
smsCompletionHandler = completion
// initiate SMS
}
// when the SMS delegate method is called, call that completion closure
func messageComposeViewController(controller: MFMessageComposeViewController!, didFinishWithResult result: MessageComposeResult) {
// do whatever you want when done
// finally, call completion handler and then release it
smsCompletionHandler?()
smsCompletionHandler = nil
}
Thus, you'd call it like so, putting the sendEmail
inside the completion closure of sendSMS
:
self.sendSMSWithCompletion() {
self.sendEmail()
}
I don't know what your sendSMS
and sendEmail
are doing, but if you're calling the MessageUI
framework, you'd generally do that on the main queue. But if you really need to do the above on your dedicated queue, then feel free to dispatch it there. But hopefully this illustrates the concept: (a) supply completion handler closure; (b) save it so your delegate can call it; and (c) when delegate is called, use that closure property and then reset it.
Upvotes: 2
Reputation: 87
one way to do it, and it works is to put:
dispatch_async(myQueue, { () -> Void in
self.SendEmail();
});
at the end of the delegate. But i dont know if this is the only way to do this.
Cheers
Upvotes: 0