2011-02-07 4 views
9

-[NSRunLoop runUntilDate:]으로 전화하는 것이 일반적입니까? 아무런 문제없이 작동하는 것처럼 보이지만 실행 루프 내에서 실행 루프를 실행하도록 신경 쓰게 만듭니다.- [NSRunLoop runUntilDate :]를 호출하는 것이 좋습니다.

상세 정보 :

내가 지금 프로젝트를 가질 수는 REST 서비스에서 데이터를 가져 오는 있습니다. 획득해야 할 중요한 정보 중 하나는 유효한 데이터가있는 날짜의 범위입니다. 한 번만 가져올 필요가있는 매우 작은 데이터이기 때문에 로컬 변수가 nil 인 경우 데이터를 다운로드하는 것이 가장 좋은 방법이라고 판단했습니다. ASIHTTPRequestASINetworkQueue을 사용하고 있으므로 모든 것이 기본적으로 비동기이며이 작업을 수행하려면 데이터가 다운로드되어 처리 될 때까지이 속성을 반환 할 수 없습니다. 여기에 내 코드의 개요이다, 변수의 이름은 무죄를 보호하기 위해 변경되었습니다 :

__block BOOL isWorking = YES; 
__block ASIHTTPRequest *request = [[[ASIHTTPRequest alloc] initWithURL:/*actual URL*/] autorelease]; 
[request setCompletionBlock:^{ 
    // set local variable 
    isWorking = NO; 
}]; 
[request setFailedBlock:^{ 
    // show alert to user 
    isWorking = NO; 
}]; 
[queue addOperation:request]; 

while (isWorking) { 
    [[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.1]]; 
} 

는 다시, 이것은 잘 작동하는 것 같군. 이 접근법을 사용할 때 잠재적 인 문제점이 있습니까?

답변

3

겹치는 호출 트리가 완전히 재진입하는 경우가 아니라면 실행중인 루프에서 호출 할 수있는 메소드에서이 작업을 수행하지 않아야합니다.

코코아 터치 UI 코드는 재진입 성으로 문서화되어 있지 않습니다 (사실, Apple DTS에서는 경고/힌트가 없습니다). 따라서 fetch 데이터 핸들러가 UI 메소드에 의해 어떤 방식 으로든 호출 될 수 있다면 (또는 UI 실행 루프에서 호출 할 수있는 다른 비 재진 코드), 내부에서 UI 실행 루프를 호출하는 것은 좋지 않습니다.

+0

그래서,이 경우 소리 이 속성은 데이터를 다운로드하는 중일 때 사용합니다. 그러나 사용자가 통화 중일 때 버튼을 눌렀다가 다시 해당 부동산에 전화를 걸면 상황이 악화 될 수 있습니다. 알아 둘만한. –

+0

이 속성은 모든 UI 메서드 또는 대리자에 의해 직접 또는 간접적으로 사용됩니까? 그렇다면 여전히 큰 문제입니다. – hotpaw2

+0

UI가 사용자에게 표시되기 전에 앱이 처음로드 될 때만이 코드가 한 번만 나타납니다. 그 후에 데이터가 거기에있을 것이고 로컬 변수를 사용할 것입니다. 어떤 이유로 든 데이터를 다운로드 할 수 없으면 사용자에게 모달 경고를 표시하고 성공적으로 다운로드 될 때까지 앱에 들어갈 수 없습니다. –

4

네트워킹 코드의 비동기 완료 이벤트에 응답하여 일종의 스피너를 표시하고 해체하는 것이 더 좋지 않습니까? 유사 :

[self displayLoadingSpinner]; 
[request setCompletionBlock:^{ 
    [self handleSuccess]; 
    dispatch_async(dispatch_get_main_queue(), ^{ 
     [self hideLoadingSpinner]; 
    }]; 
}]; 
[request setFailedBlock:^{ 
    [self handleFailure]; 
    dispatch_async(dispatch_get_main_queue(), ^{ 
     [self hideLoadingSpinner]; 
    }]; 
}]; 
[queue addOperation:request]; 

나는 이것을 실행 루프로 원 클릭하는 것보다 더 좋다고 생각합니다. 그러나 여러분은 이미 이것을 알고 있고 runloop 솔루션에 정확한 단점이 무엇인지 알고 싶을 수 있습니다.


당신이 가치가 준비 될 때까지 차단하려면, 당신은 세마포어를 사용할 수 있습니다 :이 방법은 안전 같이 부를 수있는 다른 아무것도 없기 때문에

dispatch_semaphore_t sem = dispatch_semaphore_create(0); 
[request setCompletionBlock:^{ 
    dispatch_semaphore_signal(sem); 
}]; 
[queue addOperation:request]; 

dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER); 
dispatch_release(sem); 
+0

위임자/콜백 메서드 접근이 가능할 경우 취할 방식입니다. 이 경우 속성에서 반환하기 전에 값을 설정해야합니다. 그렇지 않으면 응용 프로그램이 잘못된 데이터를 계속 사용합니다. 디자인 패턴이 작동하도록 코드를 리팩토링 할 수 있습니다. 이 질문은 내 접근 방식에 예기치 않은 문제가있을 수 있는지를 알아내는 것입니다. –

+0

세마포어 접근 방식이 주 스레드를 차단하지 않습니까? 블록이 실행되는 것을 막지 않을까요? –

+0

사용하는 HTTP 라이브러리가 어떻게 구현되는지에 따라 다릅니다.예, 주 스레드가 차단되므로 라이브러리가 주 스레드를 사용하는 경우 세마포를 사용할 수 없습니다. – zoul

관련 문제