2016-07-28 3 views
1

GCD의 블록에 있었을 때 항상 __weak에 대한 참조는 self이었습니다. 누구나 추천합니다. GCD에서 self (테스트 됨)에 대한 강력한 참조가 유지 사이클을 생성 할 수 없다는 것을 알고 있습니다. 애플 블록이 실행되면 selfnil가 없을 것을 보장하기 위해 자동으로 __weak 기준과 그 기준에 _week__strong 기준을 사용하도록 권장.iOS - GCD에 대한 약하고 강력한 참조

- (IBAction)startGCD:(id)sender { 

    GCDVC* __weak weakSelf = self; 

    [self.activityIndicator startAnimating]; 

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{ // 1 

     // VC2* __strong strongSelf = weakSelf; 

     [weakSelf.proArray addObject:@"2"]; 

     [NSThread sleepForTimeInterval:10]; 

     NSLog(@"%@",weakSelf.proArray); 

     dispatch_async(dispatch_get_main_queue(), ^{ // 2 
      [weakSelf.activityIndicator stopAnimating]; 
     }); 
    }); 

} 

테스트 1 I 버튼을 누르고 표시가 회전되어

나는 다음과 같은 코드 조각이있다. GCD가 끝나기 전에 뒤로 버튼을 누르고 GCDViewController가 해제됩니다.

테스트 2 그런 다음 자신에 대한 강력한 참조를 제거하고 동일한 절차를 실행합니다. GCDViewController는 블록이 작업을 마칠 때까지 해제되지 않습니다. 그러나 그 때 풀어 놓았다.

테스트 지금은 내가 2

그래서 자기가 전무되지 않습니다 있는지 확인하려면 테스트와 정확한 동작을 (__weak 또는 __strong없이) 자체를 직접 참조하는 경우 3 블록이 실행될 때 self에 대한 __weak 참조를 참조하는 __strong 참조를 사용하는 지점이 무엇입니까? 내가 여기 뭔가보고 싶니? 테스트 2 & 3의 결과를 변경하는 예제가 있습니까?

+0

당신은 블록이 실행되는 동안 자기가 해제됩니다 어떤 시나리오를 방지하기 위해 블록 내부의 강한 참조를 만듭니다. – dan

+0

예 알아요. 그러나 __strong과 self의 차이점은 무엇입니까? 내가 직접 자기 자신을 호출하면 나는 __strong과 같이 셀 수를 늘린다. 그리고 출력은 두 경우 모두 같습니다. – BlackM

+0

블록에서 직접 self를 참조하면 블록이 주변에있는 동안 자체가 할당 해제되지 않습니다. 블록 외부에 약한 자기를 생성 한 다음 내부가 강한 자체를 생성하면 블록이 주변에있는 동안 자체를 할당 취소 할 수 있으며 블록이 실행되는 동안 만 자체를 차단합니다. – dan

답변

5

내가 블록 GCD에있을 때 항상 자기에 대한 __weak 참조를 사용했습니다. 누구나 추천합니다.

아니요. 나는 그런 사람을 권해드립니다. 약한 참조는 유지 사이클이있는 일부 상황에서 의미가 있습니다. 그러나 블록 (에 하나 self 점 포함) 객체에 약하거나 강한 참조를 캡처해야하는지 여부 것은 내가 스스로 강한 참조 (테스트 것을 알고 특정 메모리 관리 문제의 코드의 디자인과

에 따라 달라집니다)를 GCD로 작성하면 주기를 유지할 수 없습니다.

블록을 글로벌 또는 메인 큐의 dispatch_async으로 전달하면 절대로 보존주기가 생성되지 않습니다. 나는 (__weak 또는 __strong없이) 자체를 직접 참조하면

지금 나는 어쩌면 당신은이 경우에 어떤 차이가 표시되지 테스트 2.

와 정확한 동작이있다. 그러나 그들은 일반적으로 다른 행동을합니다. 기본적으로 질문은 self이 가리키는 개체에 대한 강함 또는 약한 참조를 캡처하는 블록의 차이점입니다.

현재 개체 (self이 가리키는 개체)가 잠재적으로 해당 블록을 제외하고 강력한 참조를 보유하는 다른 모든 개체에 의해 해제되고 그 이후에 블록이 비동기 적으로 실행되면 차이가 발생합니다.

  • 블록이 현재 개체에 대한 강력한 참조를 캡처 한 경우 해당 참조는이 전체 시간 동안 개체를 유지합니다. , 현재 개체가 이미 해제 된 그래서 객체는 여전히 살아 있고 블록이 현재 객체에 대한 약한 참조를 캡처 한 경우 우리는 등
  • 그것을 사용하고 메시지를 보낼 수 있습니다 때 마지막 강한 참조 풀려났다. 그래서 블록의 약한 참조는이 시점에서 nil 될 것이며, 블록은 하나 strongSelf을 확인하고 그것이 nil 것을 볼 때 반환하는 것입니다 (그것으로 아무것도하지 않을 것이다, 또는 어떤이 strongSelf에 메시지를 보내드립니다 아무 것도하지 않는 nil).

그래서 하나 개의 경우 물건에서 수행되고 다른 경우 아무것도 이루어집니다.

사례의 현재 개체가보기 또는보기 컨트롤러와 같은 일부 UI 요소 인 경우보기 계층 구조에있는 한보기 계층에있는 항목에 의해 유지 될 것이므로 이 뷰/뷰 컨트롤러를 빠져 나 가면서 다른 컨트롤러에 대한 강력한 참조가없는 상황이 발생합니다. 귀하의 경우에는

, 당신은 블록 내에서 모든 일이, 즉 UI의 변경, [weakSelf.activityIndicator stopAnimating];입니다. 이 명령이 실행되었는지 여부는 중요하지 않습니다. 왜냐하면이 명령이 포함 된보기가 이미 표시되지 않기 때문입니다. 아무도이 활동 표시기를 볼 수 없습니다. 그래서 당신이 그것을 멈추게한다면 그것은 어떤 차이가 있습니까? 그러나 이것은이 경우에만 해당됩니다. 일반적으로 블록 내부의 명령이 일부 글로벌 상태를 변경하거나 네트워크 또는 무언가를 통해 무언가를 전송한다고 상상할 수 있습니다.