2009-05-28 1 views
174

Scott Stevenson이 관리하는 훌륭한 블로그를 통해 서핑을하고 있는데, 대리인에게 '할당'속성 대 '유지'를 지정하는 기본적인 Objective-C 개념을 이해하려고합니다. 두 가지 모두 가비지 수집 환경에서 동일합니다. 나는 주로 비 GC 기반 환경 (예 : iPhone)에 관심이 있습니다. .Objective-C 델리게이트는 대개 retain 대신에 속성 할당을받는 이유는 무엇입니까?

"오히려 복사하거나 유지하는 것보다, 직접 인스턴스 변수에 값을 할당하는 세터를 생성합니다 할당 키워드는이 NSInteger 및 CGFloat, 또는 같은 기본 형식에 가장 적합합니다 : 스콧의 블로그에서 직접

대리인과 같이 직접 소유하지 않은 개체 "라고 설명합니다.

대리인 개체를 직접 소유하고 있지 않다는 것이 무슨 의미입니까? 나는 그들이 내 심적으로 빠져 나가는 것을 원하지 않는다면, 저를 위해 그것을 간직 할 것입니다. 나는 대개 UITableViewController를 각각의 dataSource와 delegate로부터 추상화한다. 나는 또한 그 특별한 물건을 가지고있다. 내 UITableView 항상 주위에 해당 대리인이 있으므로 멀리 가지 않도록하고 싶습니다.

누가 내가 틀렸는 지 더 설명 할 수 있습니까? Objective-C 2.0 프로그래밍에서이 일반 패러다임을 보유 대신 대리자에 assign 속성을 사용하여 프로그래밍 할 수 있습니까?

감사합니다.

+0

"대리인"및 "아이폰"없이 태그가 지정되었습니다. –

+0

NSString 같은 복사 대신 대리인 지정 이유는 무엇입니까 – OMGPOP

답변

174
당신이 대의원을 유지하는 것은 당신이 유지주기 피할 필요가있다 피할 이유

:

A가 B A가 B의 대표 로 자신을 설정 을 만들어가 ... A는 소유자에 의해 해제

B의 경우 B가 A를 소유하고 있기 때문에 A가 보유한 A는 해제되지 않으므로 A의 dealloc은 호출되지 않고 A와 B 모두이 누출됩니다.

A가 B를 소유하고 있으므로 dealloc에서 없애 버리므로 걱정하지 않아야합니다.

+0

나는 동의하지 않는다, 마이크. 방금 모달에 모달을 기각하는 대리인이있는 문제를 발견했습니다. 그러나 모달에서 메모리 경고를하면 대리인이 해제됩니다. 그런 다음 모달을 기각 할 때 대표는 무효입니다. 추락. –

+0

그래, 나는 동의하지 않는다. 그러나 당신은 그것이 디자인 결함이라는 것이 옳다. 나는 진짜 해산의 아이 클래스를 통해 내 해고 요청을 전달했다는 것을 알았다. 그 자식 클래스가 해제되고 모달 컨테이너 위임자를 무시하고 해산 할 수 없습니다. 나는 최종 위임자에 대한 포인터를 전달하기 위해 그것을 변경했고 그 중 하나는 메모리 경고에서 해제되지 않았고 모두 좋다. –

+2

코드를 작성하지 않아서 nil 대리자가 충돌을 일으키지 않도록해야합니다. 소유 객체 만 소유 참조를 가져야합니다. dealloc 될 때, 그것들을 공개하기 전에 소유 된 객체의 델리게이트를 nil로 설정해야합니다. 그러면 nil 대리자에게 보낸 모든 메시지는 무시됩니다. 그러나 메시지에 nil 객체 *를 전달하면 메시지가 충돌 할 수 있습니다. 그냥 대리인을 그런 식으로 다루지 않도록하십시오. –

44

대리인 메시지를 보내는 개체가 대리인을 소유하고 있지 않기 때문에.

컨트롤러가 뷰 또는 윈도우의 위임자로 설정 될 때와 같이 반대 방향입니다. 컨트롤러가 뷰/창을 소유하므로 뷰/창에서 해당 대리인을 소유하면 두 개체가 모두 표시됩니다. 서로 소유하고있어. 이것은 물론, 동일한 결과 (죽은 객체가 살아 있어야 함)를 가진 누출과 유사한 유지 사이클입니다.

그 밖의 경우에는 피어입니다. 두 피어 모두 다른 피어를 소유하고 있습니다. 두 피사체가 같은 세 번째 개체에 의해 소유되어 있기 때문일 수 있습니다.

어느 쪽이든, 대리인이있는 개체는 대리자를 유지하면 안됩니다.


부록 (적어도 하나 개의 예외가 그렇고. 나는 그것이 무엇인지 기억하지 않는다, 나는 그것을위한 좋은 이유가 있었다 생각하지 않습니다.,있다() 2012-05-19 추가됨) : ARC에서 assign 대신 weak을 사용해야합니다. 약한 참조는 개체가 죽으면 자동으로 nil으로 설정되어 위임 개체가 데드 델리게이트에 메시지를 보낼 가능성을 없애줍니다.

어떤 이유에서든 ARC를 사용하지 않으려면 개체를 가리키는 속성 assignunsafe_unretained으로 변경하십시오. 이는 개체에 대한 참조가 유지되지는 않지만 영원하지 않음을 명시합니다.

assign은 ARC와 MRC 모두에서 비 개체 값에 적합합니다.

+13

'NSURLConnection'은 델리게이트를 유지합니다. –

+0

예,'weak'을 사용합니다. 그러나 원래의 질문에는 답이 없습니다 : Apple이'weak' 대신'assign'을 사용하는 이유는 무엇입니까? – wcochran

+0

@wcochran : 원래 질문은 "왜 retain * retain *"대신에 delegate 속성이 "assign"으로 주어 졌는가입니다; '약한 '존재는 존재하지 않았다. 귀하의 질문은 귀하가 별도로해야하는 질문입니다. 나는 그것에 행복하게 대답 할 것이다. –

17

할당 된 델리게이트가있을 때 객체가 할당 해제 될 때마다 해당 델리게이트 값을 항상 nil로 설정하는 것이 매우 중요하므로 객체는 dealloc에서 델리게이트 참조를 항상 무시하지 않도록주의해야합니다 그것이 다른 곳에서 그렇게하지 않았다면.

+0

"할당 된 대리자가있을 때 개체가 할당 해제 될 때마다 해당 대리자 값을 항상 nil로 설정하는 것이 매우 중요합니다."왜? –

+2

어떤 왼쪽 참조 세트도 객체가 할당 해제 된 후에는 유효하지 않으므로 (예상되는 객체 종류에 더 이상 할당되지 않은 메모리를 가리킴) 사용하려고하면 충돌이 발생합니다. 디버거에서이 기호는 디버거가 일부 변수의 유형이 실제로 변수가 실제로 선언 된 것으로부터 잘못되었다고 주장하는 경우입니다. –

+1

대리인 인 개체가 타이머 또는 다른 비동기 콜백과 같은 다른 소스에 보관되는 경우에만 필요합니다. 그렇지 않으면 해제 한 후에 할당이 취소되고 대리자 메서드를 호출하지 않습니다. –

1

그 이유 중 하나는 유지주기를 피하는 것입니다. A와 B가 둘 다 서로를 참조하고 어느 것도 메모리에서 해제되지 않는 시나리오를 피하기 위해.

Acutally 은 NSInteger 및 CGFloat와 같은 기본 유형 또는 직접 소유하지 않은 객체 (예 : 대리인)에 가장 적합합니다.

+0

오히려 OP의 인용문과 받아 들여진 답변에서 각각 복사 한 것입니까? 아닙니다. – dakab

관련 문제