2014-04-17 2 views
0

iOS 앱을 작성 중이며 코드의 일부는 특정 작업에서 반환 된 성공/실패 값을 사용합니다.이 작업에는 라이브러리의 콜백이 포함됩니다. 콜백이 성공/실패를 반환 한 후에 만 ​​반환되는이 작업의 반환 값을 원합니다. 그러나 순차 코드를 작성한 이후 콜백이 성공/실패를 반환하기 전에 반환 값이 반환됩니다.실행을 계속하기 전에 비동기 작업 완료를 보장하는 방법

모달 뷰 컨트롤러를 사용하여 보았습니다.이 뷰 컨트롤러에서 작업을 실행 한 다음 코드를 다시 반환 할 수 있음을 이해합니다.

그러나 이것은 콜백 시퀀스를 시작하는 코드가 실행될 때 새로운보기 컨트롤러가 표시되는 것을 원하지 않기 때문에 내 요구 사항에도 맞지 않습니다. 사용자에게 정보를 요구하는 특정 콜백이 있지만. popover에서 이것을 수행하고 Popover 모달 내에서 View Controller를 만드는 것을 고려했습니다. 그러나 콜백은 여전히 ​​메인 스레드의 일부가 될 것이고 popover가 모달로 제공 될 때 (?) 그들을받지 못할 것입니다.

이러한 개념에 대한 현재의 이해를 통해 나는 어떻게 진행해야할지 모릅니다. iOS에서이 작업을 수행 할 수있는 방법이 있습니까?

편집 : 코드는 당신이 GCD를 사용하여이

//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 
} 
+0

당신은 한 번 비동기 방식이 이루어집니다 따라 트리거됩니다 대리자 메서드를 사용할 수 있습니다. – Larme

+0

일부 코드를 입력하십시오 – suhit

답변

1

같은 것을한다. 예를 들어 :

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); 
-1

당신은 블록을 반환 할 때까지 실행을 지연하기 위해 세마포어를 사용할 수 있습니다

__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); 
+0

답변 해 주셔서 감사합니다. 게시 된 코드와 관련하여'TaskController'의 모든 함수가이 블록에 속해야합니까? 이 블록의 일부인 onCallback 함수없이 콜백을 얻는 다른 방법이 있을까요? – itsmeIcarus

+0

블록을 반드시 가져야하는 것은 아닙니다. 요점은'dispatch_semaphore_signal (semaphore);'를 호출 할 때'dispatch_semaphore_wait (semaphore, DISPATCH_TIME_FOREVER); '로 현재 스레드를 차단하고 실행을 계속한다는 것입니다. 물론이 두 호출은 같은 스레드에있을 수 없습니다. 왜냐하면이 스레드는 무한정 스레드를 차단할 것이기 때문입니다. – Levi

+0

스레드를 차단하여 비동기 작업의 결과를 얻고 결과를 최종적으로 사용할 수있게 된 후에도 프로그램을 계속 진행할 필요는 없습니다. 사실, 그것은 코드 냄새입니다. julie의 답을 살펴볼 수도 있습니다. 이는 합리적인 접근 방법 중 하나입니다. – CouchDeveloper

관련 문제