2014-11-03 3 views
0

나는 비 ARC 환경사용하여 자기와 자기 특성

에 블록 내부의 자기를 사용할 때 메모리 관리에 대해 잘 알고 블록을 사용하고있다 그러나 나는 두 가지 특정 질문이 :

__block MyClass *blockSelf = self; 
self.myBlock = ^{ 
    blockSelf.someProperty = abc; 
    [blockSelf someMethod]; 
}; 

것은이 AVO됩니다

1) 난의 보관주기를 차례로 자기가 만들 수 있습니다 사용하여 유지 블록을 방지하기 위해 다음과 같이 할 __block을 사용할 수 있습니다 이해 이드는 확실히주기를 유지하지만, 이렇게함으로써 나는 스스로를 풀어 놓을 수있는 범위를 만들었고, 결국 다른 누군가에 의해 할당이 해제되었다. 그래서 이것이 일어 났을 때 self는 없어졌고 blockSelf는 쓰레기 값을 가리키고 있습니다. 자체가 할당 해제 된 후에 블록이 실행될 때 조건이있을 수 있습니다. 그런 다음 블록은 할당 해제 된 인스턴스를 사용하려고 할 때 충돌합니다. 우리는 어떻게이 상태를 피할 수 있습니까? 블록이 실행될 때 blockSelf가 유효한지 확인하고, self가 할당 해제되었을 때 블록 실행을 중단시키는 방법. 비슷한 라인에

2) 나는 다음과 같은 블록을 사용한다고 가정

__block MyClass *blockSelf = self; 
self.myBlock = ^{ 
     [blockSelf someMethod:blockSelf.someProperty]; 
    }; 

// I am taking someProperty in an method argument 
-(void) someMethod:(datatype*)myClassProperty 
{ 
    myClassProperty = abc; 
} 

이제 (이 여러있을 때 일어날 수 자체가 해제되지 않고 someProperty는 것으로 someMethod의 실행이 시작되기 전에 발표하는 상황이있을 수있다 스레드). 내가 self.someProperty = nil을하더라도; 릴리스 될 때 myClassProperty는 nil이 아니며 일부 쓰레기를 가리키고 있으므로 someMethod가 실행되면 첫 번째 행이 충돌로 이어집니다. 어떻게 이것을 피할 수 있습니까? 당신이 myBlock을 사용하는 방법 2

+0

1) '__block'이 아니라'__weak'이 될까요? – trojanfoe

+0

http://dhoerl.wordpress.com/2013/04/23/i-finally-figured-out-weakself-and-strongself/ (__block이 아니라고 선언해야합니다) – l0gg3r

+2

나는 비 아크 환경이므로 __weak을 사용할 수 없습니다. –

답변

3
  1. 이것은 비 -ARC 코드의 다른 모든 곳의 영이 아닌 약한 참조와 같은 문제입니다 (예 : 위임자 등 (MRC에는 약한 참조가 없으므로 MRC의 약한 참조 사항이지만 ARC 일 이전에는 여전히 안전한 코드를 작성할 수 있습니다.)

    기본적으로 솔루션은 소유권에 대한 명확한지도가 필요하다는 것입니다. self은 블록을 활성 상태로 유지합니다. 또는 일부 다른 객체가 블록을 활성 상태로 유지해야합니다.

    예를 들어 대리인의 경우 "부모"개체는 "자식"개체의 대리자입니다. 이 경우 "부모"객체는 "자식"객체를 활성 상태로 유지할 책임이 있으므로 "부모"객체가 "자식"객체보다 수명이 길어서 후면 참조가 약하고 안전합니다 (자식 객체의 메서드가 부모 객체가 살아있을 때 부모 객체에 의해서만 호출 될 수 있습니다).

    반면에 비동기 작업이 있고 해당 블록이 콜백으로 작업에 제공되면 일반적으로 작업이 해당 블록을 유지해야합니다. 이 경우 self은 블록을 점유하지 않습니다. 그리고 블록은 self에 대한 강력한 참조를 유지하므로 작업이 완료되면 self에서 수행해야하는 작업을 안전하게 수행 할 수 있습니다.실제로, 어떤 오브젝트 self 이건간에, 비동기 작업에 의해 간접적으로 유지되기 때문에, 그것을 사용하는 사람에 의해 유지 될 필요조차 없습니다. 그것은 단지 생성, 실행 및 잊을 수있는 종류 일 수 있습니다.

    블럭이 때때로 self에 의해 살아 있고, 때로는 뭔가 다른 것으로 살아있는 경우, 디자인을 다시 생각해야합니다. "자기가 할당 해제 된 후 블록이 실행될 때 조건이있을 수 있습니다."라고 말합니다. 글쎄, 당신은 전체 디자인과 이것이 어떻게 일어날 수 있는지 기술해야한다. 일반적으로 비동기 적으로 실행되는 항목의 경우 self은 블록을 보유 할 필요가 없습니다.

  2. 코드가 실제로 혼란스럽고 이해가되지 않습니다. 예를 들어 매개 변수 (myClassProperty)에 할당하는 이유는 무엇입니까? 매개 변수가 어쨌든 덮어 쓰기 될 때 인수를 전달하는 요점은 무엇입니까? 왜 로컬 변수 이름을 "myClassProperty"으로 지정 하시겠습니까?

    나는 당신이 다른 스레드에서 변경할 수있는 속성에 액세스하는 방법과 그 메모리 관리를 처리하는 방법에 대해 질문하고 있다고 생각합니다. (이 질문은 블록이나 ARC/MRC와는 관련이 없으며 ARC에서도 똑같이 문제가됩니다.)

    답변은 원자 속성이 필요하다는 것입니다. 동기화 된 속성 atomic을 만들거나 방법을 알고있는 경우 원자 속성을 수동으로 구현할 수 있습니다. 객체 포인터 유형의 원자 속성은 getter가 기본 변수를 반환 할뿐만 아니라이를 유지하고 자동 릴리스하여 결과를 반환해야 할 필요가 있습니다. getter에서 검색 및 유지는 오래된 값의 릴리스와 새 값의 보유를 포함하는 setter의 중요 섹션과 동기화 된 중요한 섹션에서 발생합니다. 기본적으로이 동기화는 값을 검색하여 getter에 유지하는 사이에 값이 설정자에서 해제되지 않도록합니다. 그리고 getter에서 반환 된 값은 유지되고 자동 렌더링되므로 범위가 지속되는 동안 보장됩니다.

+0

당신은 요점을 얻지 못했습니다. 그는 속도 저하가 필요없고 동기화 속성으로 앱을 동기화합니다. 'someMethod' 메쏘드가 수행 중일 때 더 이상 someProperty에 값이 필요 없지만 변수 myClassProperty는 기존 값이나 nil을 가져야합니다. MRC에서 그의 코드가 멀티 스레딩 환경에서 보장 할 수없는 것이있을 수 있습니다. ARC에서 수행 한 것과 동일한 코드이기 때문에 내 솔루션이 훨씬 안전합니다. 변수'p'는 어떤 경우에도 값을 유지하거나 nil을 유지합니다. –

+1

@ Cy-4AH : 아니요. 코드가 안전하지 않으면 코드가 안전하지 않습니다. (속성이 비 원자형 인 경우 둘 다 안전하지 않으므로 원자이면 안전합니다.) – newacct

+0

Java에서 Objective-C를 찾았습니다. java에서이 코드는 안전하지 않을 수 있습니다. null에서 메서드를 호출하면 예외가 발생하기 때문입니다. 그러나 Objective-C에서는 메시지를 nil로 보내는 것이 안전합니다. 그리고 그것은 일반적인 관행입니다. –

-2

솔루션)의 경우 1

__block MyClass *blockSelf = self; 
self.myBlock = ^{ 
     datatype* p = [blockSelf.someProperty retain]; 
     [blockSelf someMethod:p]; 
     [p release]; 
    }; 

// I am taking someProperty in an method argument 
-(void) someMethod:(datatype*)myClassProperty 
{ 
    myClassProperty = abc; 
} 

) 모른다. self으로 만 사용하는 경우 모두 정상입니다. 그리고 그것이 다른 객체에 의해 사용된다면, 그것은 또한 self에 레퍼런스를 유지해야하며, 또한 모두 괜찮을 것입니다.

+0

이것은 명백하고 정확할 수도 있지만, 내 메서드에서 다른 속성을 사용하는 경우에도 5 개의 속성을 사용하고 각 속성을 유지 한 다음 해제한다는 것이 맞지 않을 경우 어떻게해야합니까? –

+0

@ tarun_sharma, 왜 이해가 안되니? 아크도 똑같이합니다. 그것은 당신에게'retain-release' 코드를 추가합니다. 그리고 다섯 가지 주장을하는 방법이 있습니까? 못 생겼다고 생각하니? 이 경우 당신은'someMethod'에 인자로 전달하지 않고 직접 속성들과 작업해야합니다. –

+0

(2)에 대한 해결책은 OP 코드보다 안전하지 않습니다. OP가 속성에 액세스하여 메서드에 전달할 때 사이에 공개되는 값에 대해 걱정한다면 OP 코드와 마찬가지로 속성에 액세스하고 유지하는 사이에 값이 공개됩니다. 두 가지 모두에 대한 솔루션은 원자 속성입니다. – newacct