IT이야기

NSURLSession과 함께 NSOperationQueue 사용

cyworld 2021. 4. 24. 09:51
반응형

NSURLSession과 함께 NSOperationQueue를 어떻게 사용합니까?


다운로드 할 이미지를 대기열에 즉시 추가 할 수있는 대량 이미지 다운로더를 구축하려고합니다. 진행 상황과 다운로드 완료시기를 확인할 수 있습니다.

내 독서를 통해 NSOperationQueue대기열 기능과 NSURLSession네트워크 기능이 내 최선의 선택처럼 보이지만 두 가지를 함께 사용하는 방법에 대해 혼란 스럽습니다.

의 인스턴스를 NSOperation추가 NSOperationQueue하고 대기열에 추가 된다는 것을 알고 있습니다 . 그리고 NSURLSessionDownloadTask여러 작업이 필요한 경우, 여러 작업을 사용하여 다운로드 작업을 만드는 것 같지만 두 작업을 어떻게 합쳤는지 잘 모르겠습니다.

NSURLSessionDownloadTaskDelegate 다운로드 진행 및 완료 알림에 필요한 모든 정보를 가지고있는 것 같지만 특정 다운로드를 중지하고 모든 다운로드를 중지하고 다운로드에서 얻은 데이터를 처리 할 수 ​​있어야합니다.


여기서 당신의 직감이 맞습니다. 많은 요청을 발행하는 경우 NSOperationQueuewith maxConcurrentOperationCount4 또는 5를 갖는 것이 매우 유용 할 수 있습니다. 그렇지 않은 경우 많은 요청 (예 : 50 개의 큰 이미지)을 발행하면 느린 네트워크 연결 (예 : 일부 셀룰러 연결)에서 작업 할 때 시간 초과 문제가 발생할 수 있습니다. 작업 대기열에는 다른 이점도 있지만 (예 : 종속성, 우선 순위 할당 등) 동시성 정도를 제어하는 ​​것이 IMHO의 주요 이점입니다.

completionHandler기반 요청을 사용하는 경우 작업 기반 솔루션을 구현하는 것은 매우 간단합니다 (일반적인 동시 NSOperation하위 클래스 구현입니다. 자세한 내용은 동시성 프로그래밍 가이드작업 대기열에서 동시 실행을위한 작업 구성 섹션 참조 ).

delegate기반 구현을 사용하는 경우 일이 꽤 빨리 시작됩니다. 이는 NSURLSession작업 수준 대리자가 세션 수준에서 구현 되는 이해할 수있는 (하지만 매우 성가신) 기능 때문입니다 . (생각해보십시오 : 서로 다른 처리가 필요한 두 개의 서로 다른 요청이 공유 세션 개체에서 동일한 대리자 메서드를 호출하고 있습니다. Egad!)

NSURLSessionTask작업에서 델리게이트 기반 래핑하는 것은 수행 할 수 있지만 (나 및 다른 사람들이 수행했음을 확신합니다) 세션 개체가 작업 작업 개체와 함께 작업 식별자를 상호 참조하는 사전을 유지하도록하는 다루기 힘든 프로세스를 포함합니다. 작업 개체에 전달 된 이러한 작업 대리자 메서드를 전달한 다음 작업 개체가 다양한 NSURLSessionTask대리자 프로토콜을 따르도록합니다 . 세션에 스타일 기능을 NSURLSession제공하지 않기 때문에 상당히 많은 작업이 필요합니다 maxConcurrentOperationCount( NSOperationQueue종속성, 완료 블록 등과 같은 다른 장점 은 말할 것도 없음 ).

그러나 운영 기반 구현은 백그라운드 세션을 사용하는 약간의 시작이 아니라는 점을 지적 할 가치가 있습니다. 업로드 / 다운로드 작업은 앱이 종료 된 후에도 계속 잘 작동하지만 (좋은 점, 이는 백그라운드 요청에서 상당히 필수적인 동작입니다), 앱이 다시 시작되면 작업 대기열과 모든 작업이 사라집니다. . 따라서 NSURLSession백그라운드 세션에 대해 순수한 델리게이트 기반 구현 을 사용해야 합니다.


개념적으로 NSURLSession은 작업 대기열입니다. 완료 핸들러에서 NSURLSession 태스크와 중단 점을 재개하면 스택 추적이 상당히 드러날 수 있습니다.

다음은 NSURLSession 에 대한 충실한 Ray Wenderlich의 튜토리얼에서 NSLog완료 핸들러 실행시 중단 점에 추가 된 명령문을 포함합니다.

NSURLSession *session = [NSURLSession sharedSession];
[[session dataTaskWithURL:[NSURL URLWithString:londonWeatherUrl]
          completionHandler:^(NSData *data,
                              NSURLResponse *response,
                              NSError *error) {
            // handle response
            NSLog(@"Handle response"); // <-- breakpoint here       

  }] resume];

NSOperationQueue 직렬 대기열 중단 점

위에서 우리는에서 실행되는 완료 핸들러를 볼 수 있습니다 Thread 5 Queue: NSOperationQueue Serial Queue.

따라서 내 생각에 각 NSURLSession은 자체 작업 대기열을 유지하고 세션에 추가 된 각 작업은 내부적으로 NSOperation으로 실행됩니다. 따라서 NSURLSession 개체 또는 NSURLSession 작업을 제어하는 ​​작업 대기열을 유지하는 것은 의미가 없습니다.

NSURLSessionTask 자체가 이미 같은 동등한 방법 제공 cancel, resume, suspend, 등을.

자신의 NSOperationQueue를 사용하는 것보다 제어력이 적다는 것은 사실입니다. 그러나 다시, NSURLSession은 의심 할 여지없이 그 부담을 덜어주는 새로운 클래스입니다.

요점 : 번거롭지 않지만 제어력은 줄이고 Apple이 사용자를 대신하여 네트워크 작업을 유능하게 수행하도록 신뢰한다면 NSURLSession을 사용하십시오. 그렇지 않으면 NSURLConnection 및 자체 작업 대기열을 사용하여 직접 롤링하십시오.


업데이트 :executingfinishing속성은 현재의 상태에 대한 지식을 보유 NSOperation. 당신은 일단 finishing로 설정 YES하고 executingNO마무리, 당신의 작업이 고려된다. 이를 처리하는 올바른 방법은 a가 필요하지 않으며 dispatch_group단순히 비동기로 작성할 수 있습니다 NSOperation.

  - (BOOL) isAsynchronous {
     return YES;
  }

  - (void) main
    {
       // We are starting everything
       self.executing = YES;
       self.finished = NO;

       NSURLSession * session = [NSURLSession sharedInstance];

       NSURL *url = [NSURL URLWithString:@"http://someurl"];

       NSURLSessionDataTask * dataTask = [session dataTaskWithURL:url completionHandler:^(NSData *data, NSURLResponse *response, NSError *error){

          /* Do your stuff here */

         NSLog("Will show in second");

         self.executing = NO;
         self.finished = YES;
       }];

       [dataTask resume]
   }

이 용어 asynchronous는 오해의 소지가 있으며 UI (기본) 스레드와 백그라운드 스레드의 차이점을 의미하지 않습니다.

경우 isAsynchronous에 설정되고 YES, 그 코드의 일부는 비동기 대하여 실행된다는 것을 의미한다 main방법 . 다르게 말하면 메서드 내에서 비동기 호출이 이루어 main지고 기본 메서드가 완료된 후에 메서드가 완료 됩니다.

Apple OS에서 동시성을 처리하는 방법에 대한 슬라이드가 있습니다 : https://speakerdeck.com/yageek/concurrency-on-darwin .

이전 답변 : dispatch_group_t. GCD에 대한 유지 카운터로 생각할 수 있습니다.

하위 클래스 main메서드 에서 아래 코드를 상상해보십시오 NSOperation.

- (void) main
{

   self.executing = YES;
   self.finished = NO;

   // Create a group -> value = 0
   dispatch_group_t group = dispatch_group_create();

   NSURLSession * session = [NSURLSession sharedInstance];

   NSURL *url = [NSURL URLWithString:@"http://someurl"];

    // Enter the group manually -> Value = Value + 1
   dispatch_group_enter(group); ¨

   NSURLSessionDataTask * dataTask = [session dataTaskWithURL:url completionHandler:^(NSData *data, NSURLResponse *response, NSError *error){


      /* Do your stuff here */

      NSLog("Will show in first");

      //Leave the group manually -> Value = Value - 1
      dispatch_group_leave(group);
   }];

   [dataTask resume];

  // Wait for the group's value to equals 0
  dispatch_group_wait(group, DISPATCH_TIME_FOREVER);

  NSLog("Will show in second");

  self.executing = NO;
  self.finished = YES;
}

NSURLSession을 사용하면 대기열에 작업을 수동으로 추가하지 않습니다. - (NSURLSessionDataTask *)dataTaskWithRequest:(NSURLRequest *)requestNSURLSession 의 메소드 사용하여 데이터 작업을 생성 한 다음 시작합니다 (reume 메소드 호출).

작업 대기열을 제공 할 수 있으므로 대기열의 속성을 제어하고 원하는 경우 다른 작업에도 사용할 수 있습니다.

데이터 작업에 대해 수행하는 NSOperation (즉, 시작, 일시 중지, 중지, 다시 시작)에 대해 수행하려는 일반적인 작업입니다.

다운로드 할 이미지 50 개를 대기열에 넣으려면 NSURLSession이 제대로 대기열에 추가 할 50 개의 데이터 작업을 생성하면됩니다.


If you're using OperationQueue and don't want each operation to create many simultaneous network requests, you can simply call queue.waitUntilAllOperationsAreFinished() after each operation is added to the queue. They will now only execute after the previous one is completed, significantly reducing the amount of simultaneous network connections.


Maybe you are looking for this:

http://www.dribin.org/dave/blog/archives/2009/05/05/concurrent_operations/

It is a bit weird that this isn't 'builtin', but if you want to hook up NSURL stuff with NSOperation's it looks like you have to reuse the runloop in the main thread and make the operation a 'concurrent' one ('concurrent' to the queue).

귀하의 경우-후속, 종속 작업이 연결되지 않은 일반 다운로드에 관한 것이라면 NSOperation을 사용하여 얻을 수있는 이점이 확실하지 않습니다.

참조 URL : https://stackoverflow.com/questions/21918722/how-do-i-use-nsoperationqueue-with-nsurlsession

반응형