programing

iOS 6의 완료 블록에 대한 dispatch_get_current_queue ()의 대안은 무엇입니까?

nasanasas 2020. 8. 22. 08:59
반응형

iOS 6의 완료 블록에 대한 dispatch_get_current_queue ()의 대안은 무엇입니까?


블록과 완료 블록을 받아들이는 메서드가 있습니다. 첫 번째 블록은 백그라운드에서 실행되어야하며 완료 블록은 메서드가 호출 된 모든 큐에서 실행되어야합니다.

후자의 경우 항상을 사용 dispatch_get_current_queue()했지만 iOS 6 이상에서는 더 이상 사용되지 않는 것 같습니다. 대신 무엇을 사용해야합니까?


"발신자가 어떤 대기열에서든 실행"하는 패턴은 매력적이지만 궁극적으로 좋은 생각은 아닙니다. 해당 대기열은 우선 순위가 낮은 대기열, 기본 대기열 또는 이상한 속성이있는 다른 대기열 일 수 있습니다.

내가 가장 좋아하는 접근 방식은 "완료 블록이 x, y, z 속성을 가진 구현 정의 큐에서 실행된다"고 말하고 호출자가 그보다 더 많은 제어를 원하는 경우 블록이 특정 큐로 디스패치하도록하는 것입니다. 지정할 일반적인 속성 집합은 "다른 응용 프로그램에서 볼 수있는 큐와 관련하여 직렬, 재진입 및 비동기"와 같은 것입니다.

** 편집하다 **

Catfish_Man은 아래 의견에 예를 들어 답변에 추가하고 있습니다.

- (void) aMethodWithCompletionBlock:(dispatch_block_t)completionHandler     
{ 
    dispatch_async(self.workQueue, ^{ 
        [self doSomeWork]; 
        dispatch_async(self.callbackQueue, completionHandler); 
    } 
}

이것은 기본적으로 설명하는 API에 대한 잘못된 접근 방식입니다. API가 실행할 블록 및 완료 블록을 수락하는 경우 다음 사실이 참이어야합니다.

  1. "실행 차단"은 내부 대기열에서 실행되어야합니다. 예를 들어 API에 대해 비공개이므로 해당 API의 제어를 완전히받는 대기열입니다. 이에 대한 유일한 예외는 API가 블록이 기본 대기열 또는 전역 동시 대기열 중 하나에서 실행될 것이라고 구체적으로 선언하는 경우입니다.

  2. 완료 블록은 # 1과 동일한 가정이 참인 경우가 아니면 항상 튜플 (대기열, 블록)로 표현 되어야 합니다. 예를 들어, 완료 블록은 알려진 글로벌 큐에서 실행됩니다. 또한 완료 블록은 전달 된 대기열에서 비동기로 전달되어야합니다.

이것은 단순한 스타일 포인트가 아니라, API가 교착 상태 또는 언젠가는 가장 가까운 트리에 매달릴 다른 엣지 케이스 동작으로부터 안전하려면 전적으로 필요합니다. :-)


다른 답변은 훌륭하지만 저에게 대답은 구조적입니다. Singleton에 다음과 같은 메서드가 있습니다.

- (void) dispatchOnHighPriorityNonMainQueue:(simplest_block)block forceAsync:(BOOL)forceAsync {
    if (forceAsync || [NSThread isMainThread])
        dispatch_async_on_high_priority_queue(block);
    else
        block();
}

두 가지 종속성이 있습니다.

static void dispatch_async_on_high_priority_queue(dispatch_block_t block) {
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), block);
}

typedef void (^simplest_block)(void); // also could use dispatch_block_t

그런 식으로 다른 스레드에서 디스패치하도록 호출을 중앙 집중화합니다.


dispatch_get_current_queue우선 사용에주의해야합니다 . 헤더 파일에서 :

디버깅 및 로깅 목적으로 만 권장됩니다.

코드는 전역 대기열 중 하나이거나 코드가 자체적으로 생성 한 대기열이 아니라면 반환 된 대기열에 대해 어떠한 가정도해서는 안됩니다. 코드는 해당 큐가 dispatch_get_current_queue ()에 의해 반환 된 큐가 아닌 경우 큐에 대한 동기 실행이 교착 상태로부터 안전하다고 가정해서는 안됩니다.

다음 두 가지 중 하나를 수행 할 수 있습니다.

  1. 원래 게시 한 대기열에 대한 참조를 유지하고 (을 통해 만든 경우 dispatch_queue_create) 그때부터 사용합니다.

  2. 을 통해 시스템 정의 대기열을 사용하고 사용중인 대기열을 dispatch_get_global_queue추적합니다.

이전에는 시스템에 의존하여 현재 대기중인 대기열을 추적하는 동안 효과적으로 작업을 수행해야합니다.


여전히 대기열 비교가 필요한 사람들을 위해 대기열을 레이블 또는 지정별로 비교할 수 있습니다. https://stackoverflow.com/a/23220741/1531141 확인


Apple은 더 이상 사용하지 dispatch_get_current_queue()않지만 다른 곳에 구멍을 남겼으므로 현재 디스패치 대기열을 계속 가져올 수 있습니다.

if let currentDispatch = OperationQueue.current?.underlyingQueue {
    print(currentDispatch)
    // Do stuff
}

이것은 적어도 메인 대기열에서 작동합니다. underlyingQueue속성은 iOS 8부터 사용할 수 있습니다.

원본 대기열에서 완료 블록을 수행해야하는 경우 OperationQueueGCD없이 직접 사용할 수도 있습니다 .


이것은 나도 대답입니다. 그래서 우리의 사용 사례에 대해 이야기하겠습니다.

We have a services layer and the UI layer (among other layers). The services layer runs tasks in the background. (Data manipulation tasks, CoreData tasks, Network calls etc). The service layer has a couple operation queues to satisfy the needs of the UI layer.

The UI layer relies on the services layer to do its work and then run a success completion block. This block can have UIKit code in it. A simple use case is to get all messages from the server and reload the collection view.

Here we guarantee that the blocks that are passed into the services layer are dispatched on the queue on which the service was invoked on. Since dispatch_get_current_queue is a deprecated method, we use the NSOperationQueue.currentQueue to get the caller's current queue. Important note on this property.

Calling this method from outside the context of a running operation typically results in nil being returned.

Since we always invoke our services on a known queue (Our custom queues and Main queue) this works well for us. We do have cases where serviceA can call serviceB which can call serviceC. Since we control where the first service call is being made from, we know the rest of the services will follow the same rules.

So NSOperationQueue.currentQueue will always return one of our Queues or the MainQueue.

참고URL : https://stackoverflow.com/questions/13237417/alternatives-to-dispatch-get-current-queue-for-completion-blocks-in-ios-6

반응형