2014-12-12 3 views
0

저는 iOS에서 블록을 처음 사용하고 있으며, 그 사용법에 관해 빠른 질문을했습니다. 다음 설정이 있다고 가정 해보십시오.블록 내부의 속성에 액세스하기

viewController.rowLabels = @[@"Hello", @"World"]; 
viewController.testBlock = ^(NSInteger itemIndex) { 
// here i want to access another property of the viewController called foo 
}; 

위와 같이 위에서 본 것처럼 블록 내에서보기 컨트롤러의 다른 속성에 액세스하려고합니다. 이를 달성하기 위해 * __ 약한 -> 강력한 임무를 수행해야합니까, 아니면 단순히 NSLog (viewController.foo)처럼 액세스 할 수 있습니까?

+0

맨위로 대답을 읽어 보시기 바랍니다. http://stackoverflow.com/questions/4352561/retain-cycle-on-self-with-blocks – cdstamper

+0

귀하가하려는 의도에 대해 더 많은 정보를 제공해야합니다. – vikingosegundo

답변

4

, 당신은 다른 속성처럼 액세스 할 그냥 :

viewController.rowLabels = @[@"Hello", @"World"]; 
viewController.testBlock = ^(NSInteger itemIndex) { 
    ... viewController.foo ... 
}; 

에서을 귀하의 단편 우리가 무엇을 viewController 알 수없는 - 예 이 프래그먼트가있는 메소드 나 전역 변수 등에서 로컬 변수가 될 수 있습니다. 여기에있는 것처럼 viewController의 값을 읽는 경우 [1] 중요하지 않습니다.

위의 코드는 작동하지만 문제가있을 수 있습니다. 강한 참조주기이있을 수 있습니다. viewController 인스턴스는 testBlock 속성을 통해 블록을 참조하며 블록은 viewController 인스턴스를 참조합니다. 이 두 참조가 모두 강하면 순환 의존성이 있으며 viewController 인스턴스와 블록을 절대로 시스템에서 해제 할 수 없습니다. 당신은 약한 참조를 사용하여이 사이클을 깰 수 :

viewController.rowLabels = @[@"Hello", @"World"]; 
__weak ViewController *weakViewController = viewController; // make a weak reference to the instance 
viewController.testBlock = ^(NSInteger itemIndex) 
{ 
    // temporarily make a strong reference - will last just as long as the block 
    // is executing once the block finishes executing the strong reference is 
    // removed and no strong reference cycle is left. 
    ViewController *myController = weakViewController; 
    // only execute if the `ViewController still exists 
    if (myController != nil) 
    { 
     ... myController.foo ... 
    } 
}; 

HTH

[1] 당신이 읽고있는 값이 ViewController 인스턴스에 대한 참조입니다 점에 유의하고 해당 인스턴스의 속성을 수정할 수 있습니다, 당신이 할 수없는 일 (그리고 시도하지 않는 것)은 viewController이 로컬 변수 인 경우 viewController이 참조하는 인스턴스를 수정합니다.

+1

자동 캡처 된 변수 (첫 번째 예와 같이 __ 블록 변수가 아닌 변수)는 const로 캡처되므로 변경할 수 없습니다. https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/Blocks/Articles /bxVariables.html#//apple_ref/doc/uid/TP40007502-CH6-SW1 – cdstamper

+0

@cdstamper - 정확합니다. 그러나 그들이 참조하는 대상은 아닙니다. 지역 변수가 참조하는 객체 인스턴스를 블록을 사용하여 업데이트하는 것은 아마도 더 모호한 시나리오 일 것이며 나는이 질문에서 더 이상 물을 진흙 투성이로 만들고 싶지 않습니다! ;-) – CRD

0

은과 같이, 뷰 컨트롤러 객체를 포함하는 __block 변수를 선언 :

__block __weak ViewController *blockVC = viewController; 
viewController.testBlock = ^(NSInteger itemIndex) { 
    NSLog(@"%@", blockVC.foo); 
}; 

내가 __block 암시 강한 이후 ​​모두 __block__weak을 사용했지만, 참고로 __weak를 추가하면 강력한을 깰 도움이 될 수 있습니다 참조주기 동안 여전히 할당 해제를 방지하기 위해 __block의 강력한 참조를 사용합니다.

__weak ViewController * weakVC = viewController; 
viewController.testBlock = ^(NSInteger itemIndex) { 

    ViewController * strongVC = weakVC; 
    if (strongVC) { 
     NSLog(@"%@", strongVC.foo); 
    } 
}; 

그러나 참고 : 그냥 __weak 참조를 만들 수 있다면 블록 내에서 변수와 속성에 액세스 할 __block 변수를 사용하여 반대로 아이폰 OS 5.0으로


, 그것은 보인다 __weak__block 저장 유형과 조합하여 사용하는 것과 달리 __weak은 객체를 활성 상태로 유지할 수없는 참조를 지정합니다. 즉, 할당 해제 할 수 있기 때문에 실제로 블록을 사용하기 전에 weakVC이 0이 될 수 있습니다. (다만 혼자 __weak 변수를 사용하는 경우 if (strongVC) 조건이 필요한 이유입니다.)

단순하지만, 아마도 문제가 대답
+5

나는 여기에 있었던 코멘트를 철저히 지워 버렸고 결과적으로 따르기가 거의 불가능 해졌습니다. 누구나 여기에 새 주석 집합을 추가 할 예정이라면 간결하게 작성하고, 주제에 엄격하게 적용하고, 예의 바르게 작성하십시오. –

+3

모든 공손함으로이 대답은 잘못되었습니다. @futurereader. – vikingosegundo

+0

친애하는 @furturereader. 블록에있는 객체가 오류라는 것을 의미하지만, 호출 범위가 사라 졌다는 것을 이해하시기 바랍니다. 그건 괜찮아. 범위를 계속 유지하도록 강요하지 마십시오.이 기간은 어떤 비용으로도 피하기를 원할 것입니다. 코드에 해킹이 포함되어야한다면 아키텍처가 손상되었다는 것을 증명할 수 있습니다. – vikingosegundo

관련 문제