0

을 사용하여 [AFHTTPClient getPath:...] 완료 블록으로 복귀하는 것을 피하려고합니다.AFHTTPClient 성공 및 실패 블록 내의 CFRunLoopRunInMode()

NSLog(@"start"); 
__block BOOL someCondition = NO; 
AFHTTPClient *client = [[AFHTTPClient alloc] initWithBaseURL:[NSURL URLWithString:@"http://domain.com"]]; 
[client getPath:@"my/path" parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) { 
    NSLog(@"success"); 
} failure:^(AFHTTPRequestOperation *operation, NSError *error) { 
    dispatch_async(dispatch_get_main_queue(), ^{ 
     NSLog(@"async log"); 
     someCondition = YES; 
    }); 
    while (!someCondition) { 
     CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.5, YES); 
    } 
    NSLog(@"failure"); 
}]; 

그리고 출력이 될 것으로 예상 :

내 코드는 아래와 같다

start 
async log 
failure 

하지만 그 대신 나는 단지 얻을 :

start 

CFRunLoopRunInMode()kCFRunLoopRunHandledSource을 반환하지만 디스패치 큐는 제출 된 블록을 실행하지 않습니다. 완료 블록 외부에서 동일한 코드를 실행하면 예상대로 출력됩니다.

내가 알 수없는 이유는 완료 블록에서 실행될 때 디스패치 대기열이 처리되지 않는 이유입니다.

누군가 이러한 일이 발생하는 이유에 대해 조명 해 주실 수 있습니까?

+1

* 완료 블록 *입니다. HTTP 요청 작업이 완료되면 첫 번째 블록이 호출되고 요청이 실패하면 두 번째 블록이 호출됩니다. - 일부 비동기 작업이 끝날 때까지 기다리려고 시도하는 것은 좋지 않은 생각입니다. 특히 주 스레드와 사용자 인터페이스를 차단하는 경우 특히 그렇습니다. –

+0

나는 가장자리에서 살고 싶다;) 진지하게, 나는 그것이 왜 그렇게 행동 하는지를 정말로 알고 싶다. – hectr

답변

1

완료 블록에서 실행할 때 디스패치 큐가 처리되지 않는 이유를 알 수 없습니다.

디스패치 대기열을 "실행"하지 않았으므로 (디스패치 대기열을 "실행 중"이라고는 할 수 없습니다). 실행 된 루프를 실행했습니다. 디스패치 대기열은 관련되어 있지만 다른 점입니다. 한 번에 하나의 블록 만 직렬 대기열 (예 : 메인)에서 실행할 수 있습니다. 블록이 완료 될 때까지 다른 블록을 예약 할 수 없습니다. 이를 피하는 GCD에는 API가 없습니다. 이것은 일반적으로 runloop 작업에 존재하지 않는 대기열 작업에 확실성을 부여하기 때문에 일반적으로 매우 유용합니다.

1

AFNetwork의 성공 및 실패 블록이 둘 다 기본 대기열에서 예약되고 실패 블록에서 작성한 비동기 차단도 기본 대기열에서 예약됩니다.

오류 블록이 완료 될 때까지 GCD 동기화 블록이 실행됩니다. 'while'조건은 결코 거짓이 아니므로 실패 블록은 완료되지 않으며 실행될 기회가 없습니다.