Objective-C 델리게이트가 일반적으로 유지 대신 속성 지정을받는 이유는 무엇입니까?


176

Scott Stevenson이 관리하는 멋진 블로그를 살펴보면서 대리인에게 '지정'속성과 '보존'을 할당하는 기본적인 Objective-C 개념을 이해하려고합니다. 가비지 수집 환경에서는 둘 다 동일합니다. 나는 비 GC 기반 환경 (예 : iPhone)에 주로 관심이 있습니다.

Scott의 블로그에서 직접 :

"assign 키워드는 값을 복사하거나 유지하지 않고 인스턴스 변수에 직접 값을 할당하는 setter를 생성합니다. 이는 NSInteger 및 CGFloat와 같은 기본 유형 또는 대리자와 같이 직접 소유하지 않은 객체에 가장 적합합니다."

대리인 개체를 직접 소유하지 않는다는 것은 무엇을 의미합니까? 나는 일반적으로 내 대리인을 유지합니다. 왜냐하면 그들이 심연으로 들어가기를 원하지 않으면 보유가 나를 대신해 줄 것입니다. 일반적으로 UITableViewController를 해당 dataSource에서 추상화하고 위임합니다. 또한 해당 특정 개체를 유지합니다. UITableView에 항상 대리자가 있기 때문에 결코 사라지지 않도록하고 싶습니다.

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

감사!


"대표"및 "iphone"없이 태그 재 지정되었습니다.
Quinn Taylor

NSString과 같은 복사 대신 위임 할당이 필요한 이유
OMGPOP

답변:


175

대리인 유지를 피하는 이유는 유지주기를 피해야하기 때문입니다.

A는 B A를 B의 대리인으로 설정합니다 ... A는 소유자에 의해 해제됩니다

B가 A를 유지했다면, B가 A를 소유하고 있으므로 A가 해제되지 않으므로 A의 할당 해제가 호출되지 않아 A와 B모두 발생 합니다. 누출됩니다.

A는 B를 소유하고 있기 때문에 A가 사라질까 걱정하지 않아도됩니다.


동의하지 않습니다, 마이크 방금 모달에 모달을 닫는 델리게이트가있는 문제가 있습니다. 그러나 모달에서 메모리 경고를하면 대리자가 해제됩니다. 그런 다음 모달을 닫으려고 할 때 델리게이트는 0입니다. 크래시.
Paul Shapiro

좋아, 나는 동의하지 않지만, 그것은 디자인 결함이라는 것이 옳다. 나는 실제 해고자의 자녀 클래스를 통해 해고 전화를 전달하고 있음을 알았습니다. 그 자식 클래스가 해제되어 모달의 컨테이너 대리자에게 전달하지 못했습니다. 최종 위임에 대한 포인터를 전달하도록 변경했으며 메모리 경고에서 해제되지 않았으며 모두 좋습니다.
Paul Shapiro

2
비 대리인이 충돌을 일으키는 방식으로 코드를 작성해서는 안됩니다. 소유 객체 만 소유 참조를 가져야합니다. 할당 해제되면 소유 객체의 대리자를 해제하기 전에 nil로 설정해야합니다. 그런 다음 nil 대리자에게 전송 된 모든 메시지는 단순히 무시됩니다. 그러나 메시지에 nil 객체 전달하면 충돌이 발생할 수 있습니다. 그런 식으로 델리게이트를 다루지 않도록하십시오.
David Gish

잠깐만 요- weak그렇지 않나요? 문제는 왜 assign대신에 사용 weak합니까?
wcochran

3
@ wcochran : 아니요,이 질문은 assign대신에 사용 하는 이유 입니다 retain. 질문은 ARC보다 오래되었습니다. weakstrong(와 후자의 동의어는 retainARC가 도입 될 때까지) 존재하지 않았다. 당신은 weakassign별도로 질문해야합니다 .
Peter Hosey

44

대리자 메시지를 보내는 개체가 대리자를 소유하지 않기 때문입니다.

컨트롤러가 자체적으로보기 또는 창의 대리자로 설정하는 경우와는 달리 여러 가지 방법이 있습니다. 컨트롤러가보기 / 창을 소유하고 있으므로보기 / 창이 대리자를 소유하면 두 개체가 서로를 소유하게됩니다. 물론 이것은 동일한 결과를 가진 누출과 비슷한 유지주기입니다 (죽어야하는 개체는 살아남아 있습니다).

다른 경우에는 객체가 피어입니다. 둘 다 동일한 세 번째 객체가 소유하고 있기 때문에 어느 것도 다른 객체를 소유하지 않습니다.

어느 쪽이든 델리게이트가있는 객체는 델리게이트를 유지해서는 안됩니다.

(그런데 적어도 하나의 예외가 있습니다. 나는 그것이 무엇인지 기억하지 못하며, 그만한 이유가 있다고 생각하지 않습니다.)


부록 (2012-05-19에 추가됨) : ARC에서는 weak대신 대신 사용해야 합니다 assign. 약한 참조 nil는 개체가 죽을 때 자동으로 설정 되므로 위임하는 개체가 메시지를 죽은 대리인에게 보낼 가능성을 제거합니다.

어떤 이유로 ARC에서 멀리 떨어져 있다면 최소한 assign객체를 가리키는 속성을로 변경하십시오 unsafe_unretained. 이것은 객체에 대한 유지되지 않지만 0이 아닌 참조임을 나타냅니다.

assign ARC 및 MRC 모두에서 객체가 아닌 값에 적합합니다.


13
NSURLConnection대리인을 유지합니다.

예,을 사용 weak하지만 원래 질문에 대답하지 않습니다. Apple이 왜 assign대신 사용 weak합니까?
wcochran

@wcochran : 원래의 질문은 "왜 델리게이트 속성 assign유지 되지 않고 제공됩니까"였습니다 . weak요청할 때 존재하지 않았습니다. 귀하의 질문은 다른 것이므로 별도로 문의해야합니다. 기꺼이 대답 해 드리겠습니다.
피터 Hosey

@ wcochran과 Peter, 그 질문에 다른 곳이 있습니까?
Mr Rogers

17

할당 된 델리게이트가있을 때, 객체가 할당 해제 될 때마다 항상 해당 델리게이트 값을 nil로 설정하는 것이 매우 중요합니다. 다른 곳에서 그렇게했습니다.


"할당 된 대리자가있는 경우 개체를 할당 해제 할 때마다 항상 해당 대리자 값을 nil로 설정하는 것이 매우 중요합니다."이유는 무엇입니까?
Peter Hosey

2
참조가 남아있는 참조는 오브젝트 할당이 해제 된 후 (메모리가 더 이상 예상되는 오브젝트 종류에 할당되지 않음) 무효화되므로 사용하려고하면 충돌이 발생합니다. 디버거에서 이것의 표시는 디버거가 일부 변수에 변수가 실제로 선언 된 것과 완전히 틀린 유형이 있다고 주장 할 때입니다.
Kendall Helmstetter Gelner

1
이것은 위임 한 객체가 타이머 또는 다른 비동기 콜백과 같은 다른 소스에 의해 유지되는 경우에만 필요합니다. 그렇지 않으면 릴리스 후 할당이 해제되며 대리자 메서드를 호출하지 않습니다.
Andrew Pouliot

@Andrew : 사실이지만, 항상 델리게이트를 없애는 연습을한다면 중요한 순간을 잊어 버리거나 실수로 보류 된 객체를 과도하게 유지하여 어쨌든 그대로 남아 있습니다. 대리자를 제외하면 결과는 누출이 아니라 누출이 아니라 누출입니다.
Kendall Helmstetter Gelner

1

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

Acutally의 할당은 NSInteger 및 CGFloat 같은 기본 유형에 가장 적합한, 또는 대의원으로, 직접 소유하지 않은 객체.


그것은 오히려 OP의 인용문과 수용 된 답변에서 각각 복사 된 것입니까?
dakab
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.