2013-10-05 3 views
1

iOS 앱에서 UI를 업데이트하기 전에 조건이 true가 될 때까지 기다리고 싶습니다. 나는이 같은 일을 오전 :GCD : 조건을 비동기식으로 대기합니다.

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{ 
    while (!condition) NSLog("waiting for the condition"); 
    dispatch_sync(dispatch_get_main_queue, ^{ 
    //update the UI here 
    }); 
}); 

위의 코드는 잘 작동하지만 난 동안 루프를 사용하여 대기 작업이 좋은인지, 그리고 어떻게하면 부탁드립니다 더 좋은 방법이 있는지 . 감사합니다.

--- 업데이트

조건은 실제로 4 개 BOOL 변수의 조합입니다. 각 변수는 서버의 컨텐츠 요청과 연관됩니다. AFNetworking 프레임 워크를 사용하고 있습니다. 각 요청의 완료 블록에서 관련 BOOL 변수를 YES로 설정합니다. 그래서, 실제 루프는 다음과 같이있는 동안 : 여기에 일반적인 패턴이 올바른지 동안

while (!([MyRequest request1].isFinished && [MyRequest request2].isFinished && [MyRequest request3].isFinished && [MyRequest request4].isFinished)) NSLog("waiting for the condition"); 
+0

덜 추상적 인 예를 들어 줄 수 있습니까? 확인하고 싶은이 '조건'은 정확히 무엇입니까? 다른 시나리오는 다른 접근 방식을 제안합니다 (세마포어, KVO, 반복되는 'NSTimer','CADisplayLink' 등). 그러나이 while 루프 접근법은 일반적으로 권장되지 않습니다. – Rob

+0

나는 그 질문을 단순화하려고했지만 내 질문을 더욱 악화시켰다. 세부 사항을 업데이트하십시오, @ Rob. –

+0

대단히 도움이됩니다. 이 경우, 나는 새로운 연산을 생성하고, 다른 4 개의 요청 연산에 의존하게 만든다. 수정 된 답변보기 (참고로,이 네 가지 작업의 'isFinished'속성에서 효과적으로 KVO를 수행합니다.) – Rob

답변

6

수정 된 질문에서 당신이 의존하고 싶은 4 가지 AFNetworking 작업이있는 것 같습니다. 그게 훨씬 쉽습니다. 당신은 새로운 작업을 추가하고, 다른 4 개 개의 조작에 따라이 의존 할 수 있습니다

NSOperation *operation = [NSBlockOperation blockOperationWithBlock:^{ 
    [[NSOperationQueue mainQueue] addOperationWithBlock:^{ 
     // update UI 
    }]; 
}]; 

[operation addDependency:requestOneOperation]; 
[operation addDependency:requestTwoOperation]; 
[operation addDependency:requestThreeOperation]; 
[operation addDependency:requestFourOperation]; 

[queue addOperation:operation]; 

addDependency 메커니즘 본질적으로 당신을 위해 그 다른 네 개의 각 작업의 isFinished의 KVO는 않습니다. AFNetworking과 같은 NSOperation 기반 프레임 워크 사용의 즐거움 중 하나입니다. 이런 종류의 의존성은 정말 쉽습니다.


원래 답 :

이 작업을 수행했다 당신이, 당신이 대신 세마포어를 사용할 수있는 경우, 예를 들어, 당신은 세마포를 만들 것입니다 :

dispatch_semaphore_t semaphore = dispatch_semaphore_create(0); 

당신은 당신의 비동기이 줄을 블록 기다림 :

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{ 
    dispatch_semaphore_wait(semaphore); 
    dispatch_sync(dispatch_get_main_queue, ^{ 
     //update the UI here 
    }); 
}); 

그리고 조건이 만족 될 때, 그렇지 않으면이 con dition 플래그 대신, 다음과 같습니다

dispatch_semaphore_signal(semaphore); 

이 절대적으로 필요하지 않는 한 나는 오히려 이런 슈팅 큐 (심지어 동시 글로벌 큐)를 참조하지 않는 게 좋을, 그런 말로 미루어 보아. 그 다른 코드가 세마포어 신호를 낼 수 있다면, 왜 UI 업데이트 자체를 시작할 수 없는지 모르겠습니다. 이 세마포어 기법을 사용했다면 적어도 대기 대기중인 프로세스가 글로벌 대기열이 아닌 내 자신의 생성 대기열에서 발생하게됩니다.

예를 들어, 나는 그들이의라는 개체의 someProperty 속성을 변화를 관찰 할 수있다 :


key value observing을 사용하는 당신은 많은 상황에서 사용할 수 있으며, 아마 원합니다하는 또 다른 방법입니다

obj과 같이 :

[obj addObserver:self forKeyPath:@"someProperty" options:NSKeyValueObservingOptionNew context:NULL]; 

그때 구현하는 것이 observeValueForKeyPath :

obj 개체의 someProperty 속성이 업데이트 될 때마다 observeValueForKeyPath 메서드가 호출됩니다.

참고로, 나는이 개체가 해제되기 전에, 나는 obj의 관찰자를 제거하는 것입니다 있는지 확인하십시오 것 :

[obj removeObserver:self forKeyPath:@"someProperty"]; 

분명히,이 somePropertyKey Value Coding Compliant 있다고 가정합니다. 그러나 그것이 그렇다면, 이것은 훌륭한 기술입니다.

+0

상황이 내가 액세스 할 수없는 곳에서 업데이트되어 dispatch_semaphore_signal로 신호를 보낼 수 없다고 가정 해 보겠습니다. –

+0

마지막 문의 [queue addOperation : operation]에 'queue'가 있습니까? [NSOperationQueue mainQueue]? –

+0

@ThanhPham 확실히 메인 큐가 아닙니다. 그것은 당신이 만드는'대기열 '입니다. 'NSOperationQueue * queue = [[NSOperationQueue alloc] init];'. 다른 네 가지 요청을 추가 한 대기열과 같을 수 있습니다. 네가 원한다면. – Rob

0

while(!condition) 비트는 또한 "스핀 잠금"로 알려져있다 (애플은 "전화 콜백"로를 의미) 확실히 조건을 기다리는 가장 좋은 방법은 아닙니다. 대신 NSTimer 또는 NSRunLoop을 사용해보십시오.

+0

이와 비슷한가요? while (! condition && [[NSRunLoop currentRunLoop] runMode : NSDefaultRunLoopMode beforeDate : [NSDate distantFuture]]); while 문은 여전히 ​​존재하지만 NSRunLoop 부분으로 인해 더 이상 스핀 잠금이되지 않을 것이라고 생각하십니까? –

관련 문제