0

내가 제대로하고 있는지 잘 모르겠다 - 내 응용 프로그램의 백그라운드에서 원격 URL 요청을 비동기 적으로 실행하고 싶습니다. 사용자는 기다릴 필요가 없습니다. 그러나 백그라운드에서 실행 중이므로 여러 요청을 트리거 할 수 있습니다. 나는 세마포어와 동시성을 얻지 못했다. 따라서 나는 세마포어로 요청을 보호해야한다고 생각합니다. 요청이 끝나면 MKMapView 주석에 대한 업데이트를 실행합니다. 백그라운드에서 동기식으로 요청을 실행한다는 의미입니다.큐 및 세마포 디스프

나는 아래 코드를 가지고 있지만, 현재의 세마포어 구현으로도 실패한다. 나는 여러 요청을 실행할 때

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{ 
     dispatch_semaphore_t requestSemaphore = dispatch_semaphore_create(1); 
     dispatch_semaphore_wait(requestSemaphore, DISPATCH_TIME_FOREVER); 

     MapAnnotation* theAnnotation = (MapAnnotation*)button.property; 

     [theAnnotation.data update]; //this must be protected 

     [self.mapView removeAnnotation:theAnnotation]; 
     MapAnnotation* newAnnotation = [theAnnotation.data getMapAnnotation]; 
     [self.mapView addAnnotation:newAnnotation]; 
     [self.mapView selectAnnotation:newAnnotation animated:YES]; 

     dispatch_semaphore_signal(requestSemaphore); 
    }); 

나는 dispatch_async이 오류 -이

*** Terminating app due to uncaught exception 'NSRangeException', 
reason: 'Cannot remove an observer <MKPopoverBasedAnnotationCalloutController 0x10c86bd50> 
for the key path "annotation.title" from <MKPinAnnotationView 0x11798f490> 
because it is not registered as an observer.' 

감사하지만 연속 모드에서 작동!

+0

새 요청을하기 전에 진행중인 요청을 취소 하시겠습니까? – Wain

+0

백그라운드에서 동기식으로 요청을 실행한다는 의미입니다. 기본적으로 대기열을 좋아합니다. –

답변

3

GCD를 사용하지 말고 NSOperationQueue 및 작업 (단순화를 위해 작업을 차단할 수 있음)을 사용하십시오. 그런 다음 setMaxConcurrentOperationCount:을 사용하여 한 번에 하나의 작업 (요청) 만 처리되도록 할 수 있습니다.

은 UI (지도보기)를 업데이트하기 전에 주 스레드로 다시 전환해야합니다. 그렇지 않으면 예외가 발생합니다 (현재 볼 수있는 예외의 원인 일 수 있음).

+0

주 스레드로 다시 전환하는 것이 오류의 원인입니다. 대기열도 사용합니다. 감사! –

1

세마포어가 필요하다고 생각하는 이유를 모르겠지만 직렬 대기열을 사용하십시오. 다음 접근 방식의 문제점은 무엇입니까?