问题
I am building an iOS app and some part of its code relies on the success/failure value returned from a particular task.This tasks involves callbacks from a library. I want the return value from this task to be returned only after the callback has returned either success/failure. But since I wrote a sequential code the return value is returned even before the callback returns a success/failure.
I looked into using modal view controllers and from what I understand I can make the task execute from this view controller and then return the code back.
But this also doesn't suit my requirements as when the code which initiates the callback sequence is executed I don't want a new view controller to be displayed. Although there is a certain callback which requires me to prompt the user for information. I do this in a popover and I considered making the view controller within the popover modal. But then the callbacks will still be part of the main thread and I won't receive them when my popover is presented modally(?).
With my current understanding of these concepts I don't know how to proceed. Is there some way to do this in iOS?
EDIT: The code does something like this
//In CustomTableViewController
-(void) someFunc
{
ENUM_NAME code = [TaskController startTheTask:args];
if(code == SUCCEEDED)
{
//Do Something
}
if(code == FAILED)
{
//Do Something Else
}
}
//In TaskController
-(ENUM_NAME) startTheTask:args
{
startWorkflow(args); //This function registers callback function with the library.
return finalCode; //This is returned even before it is set to SUCCEEDED/FAILED
}
-(void) onCallback:params
{
MSG_TYPE msg = [params getMsg];
if(msg == TASK_FAILED)
finalCode = FAILED;
if(msg == TASK_SUCCEEDED)
finalCode = SUCCEEDED;
if(msg == TASK_SHOW_PROMPT)
{
[PopOverController showPopOver];
}
}
-(void) onUserInfoAdded
{
//This is called when Confirm is clicked in the popover
continueWorkflow(params); //asks for the next callback to happen
}
-(void) onCancleClicked
{
//This is called when Popover is dismissed without entering Info
cancleWorkflow(params); //asks for result of the workflow through callback
}
回答1:
You can use GCD. For example:
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_group_t group = dispatch_group_create();
dispatch_group_enter(group);
dispatch_group_async(group, queue, ^{
//put one process here
dispatch_group_leave(group); //when done
});
dispatch_group_enter(group);
dispatch_group_async(group, queue, ^{
//put another process here
dispatch_group_leave(group); //when done
});
// All updates finished
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
// add last steps here after all processess are finished
});
dispatch_release(group);
回答2:
You can use a semaphore to delay the execution until a block returns:
__block dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
__block NSData *dataFromTheBlock = nil;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// block implementation
// dataFromTheBlock = some data;
dispatch_semaphore_signal(semaphore);
});
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
来源:https://stackoverflow.com/questions/23125912/how-to-ensure-completion-of-a-async-operation-before-continuing-with-execution