2009-07-31 3 views
33

그래서 나는이 모든 질문을 모두 알아 냈다고 생각했습니다. 그럼 갑자기 나는 추측 할 수없는 오류 (충돌)가 발생합니다. 그런 다음 충돌을 해결하기위한 조사를 한 후에, 나는이 중요한 부분에 대해 내가 알고 있다고 생각한 모든 것이 다소 틀린 것을 발견했다. 이들에 대한 답변을 크게 저 궤도에 다시 나의 이해를 얻을 도움이 될 것입니다 -Release, Dealloc 및 자체 참조

다음은 그냥 대답 누군가의 희망에 거기 촬영 하겠어 8 개 질문입니다. 미리 감사드립니다!

Q1) 해당 참조가 nil이면 객체에서 Release를 호출해도 괜찮습니까? 이것은 무해해야합니다, 맞죠?

Q2)은 해당 참조가 해제 0의 참조 카운트로되어있는 경우 개체에 릴리스를 호출 괜찮습니까?

Q3) 릴리스하지 않고 nil에 대한 참조를 설정해야합니까? 그것을 설정하지 않으면 어떻게됩니까?

Q4) 정말 전무와 NULL의 차이가 있습니까, 아니면 그냥에 반짝이기는 리더/개발자가 객체의 유형을 알고 도움을주는 의미 일이 그냥?

Q5) 속성을 사용하려면 '자체'포인터를 사용해야합니까?

Q6) 인스턴스 변수를 사용하려면 '자체'포인터가 사용되지 않아야합니다.

Q7) 언제 그 속성 대신 인스턴스 변수를 사용하고 싶습니까? 가치 유형 데이터 멤버는 공개되지 않았기 때문에 괜찮다고 생각합니다.

Q8)는 할당 해제 함수 내에서 객체의 할당 해제를 호출 할 필요가 있습니까? 많은 예제에서 Release가 호출되었지만 Dealloc이 아닌 것으로 나타났습니다 - 자습서가 잘못 되었습니까?

+0

Nice q.나는 방금 내가 대답하고 싶지 않은 새로운 질문을 발견했다. – typeoneerror

답변

11

아마도이 질문을 여러 가지 질문으로 나눠야 할 것입니다.하지만 물어 봅니다.

  1. 예, nil에 전송 된 모든 메시지는 작업 없음입니다.
  2. 아니요. 참조 카운트가 0 인 개체가 삭제되었거나 곧 삭제되고 모든 개체로 전송 된 메시지가 충돌하거나 예외적으로 예외를 발생시킵니다.
  3. 상황에 따라 다릅니다. 만약 당신이 -dealloc에 물건을 내놓는다면 아마 그렇지 않을 것입니다. 특정 방법으로 범위가 지정된 개체라면 아마도 그렇지 않을 것입니다. 그것이 재사용되는 ivar이라면 나는 그렇다고 말하고 싶습니다. 처음 두 경우에는 포인터를 nil로 설정하지 않으면 아무 일도 일어나지 않습니다. 보통 포인터를 더 이상 액세스 할 수 없기 때문입니다. 그러나 마지막 경우에는 할당 된 메모리를 가리키는 포인터에 계속 액세스 할 수 있습니다. 메시지를 보내거나 역 참조하려고하면 앱이 다운됩니다.
  4. 그들은 모두 객체 포인터에 사용되는 규칙 nil으로 0으로 동일하고, NULL는 다른 포인터를 사용하지만, 그들이 어떤 문제가 발생하지 않습니다 혼합된다.
  5. getter/setter 속성을 호출하려면 yes를 입력하십시오. 당신이 ivar에 접근하기를 원한다면 그것은 직접 캡슐화됩니다 (흔하지 않습니다), 아니오.
  6. 아니요, self->ivar 구문을 사용하여 인스턴스 변수에 액세스 할 수 있습니다. 실제로 ivar을 입력하면 컴파일러에서 암시 적으로 self-> 역 참조를 추가합니다.
  7. 여기에 무슨 뜻인지 확실치 않습니다.
  8. -dealloc으로 전화해야하는 유일한 시간은 -dealloc 개의 방법으로 [super dealloc];으로 전화하는 것입니다. 다른 객체의 경우 항상 -release으로 전화해야합니다.
+0

(2)에서 NSZombieEnabled를 언급해야합니다. 디버깅 문제를 쉽게 해결할 수 있습니다. – diciu

+0

"쉬운"강한 단어입니다! 나는 "더 쉬울 것"이라고 말할 것입니다. –

19

A1) [nil release]은 (아무것도하지 않습니다)가 해제 된 한 후에

A2) 호는 물체를 만지지 마십시오 괜찮습니다. 그들이 출시 된 후에는 nil로 설정해야합니다.

A3) 릴리스 된 포인터를 nil로 설정할 필요는 없지만 매달린 포인터가 표시됩니다 (즉, 개체가 유효한지 여부를 알 수 없습니다). 속성을 nil로 설정하면 기본 ivar을 해제하는 데 자주 사용되므로 메모리 누출이 발생할 수 있습니다.

A4) nil과 NULL은 모두 0이므로 기술적으로 동일합니다. self->someIvar을 :

A5) 예, 당신은

A6) 자체가 본질적으로 구조체 단지 방법이라면 그렇게 같은 인스턴스 변수에 액세스 할 수 있도록, [self someProperty]를 사용하는 것처럼, 속성 self.someProperty를 사용해야합니다. 그래도 필요는 없습니다.

A7) 어떤 이유로 든 setter/getter 메소드를 실행하지 않으려는 경우. setter가 nil 값을 허용하지 않고 변수를 해제해야 할 때 사용합니다.

A8) 릴리스가 올바른 횟수만큼 호출 될 때 dealloc이 자동으로 호출됩니다. dealloc을 직접 호출하면 안됩니다 ([super dealloc] 제외)

+1

# 5에 대해 혼란스러워합니다. 나는 뷰 컨트롤러에서 "소셜"이라 불리는 비 속성적이고 유지 된 @property를 가지고 있으며 다음 문장은 같은 것을 기록합니다 : NSLog (@ "% @", social); 및 NSLog (@ "% @", self.social); 설명 할 수 있니, 톰? – typeoneerror

+1

두 NSLog 명령문 모두 같은 객체를 출력하기 때문입니다. 차이점은'self.social'는 객체를 반환하는 메소드를 호출하고'social'는 객체 자체 일뿐입니다. –

8

다른 사람이 적절하게 대답했습니다 1-6.

(7) Apple은 init 및 dealloc에서 인스턴스 변수를 직접 사용할 것을 권장합니다. 주로 이것은 객체 (특히 하위 클래스 인 경우)가 두 메소드 모두에서 부분적으로 만 설정되고 사소한 액션 이외의 다른 것이 있으면 setters/getters를 호출하면 잘못된 동작이 발생할 수 있기 때문입니다. 일반적으로 오브젝트에서 getter를 통하지 않고 ivar에 직접 액세스 할 수 있으며, 그렇게하는 것이 효과적 일 것입니다 (iPhone에서만 관련이 있습니다). 일반적으로 모든 경우에 setter를 사용해야합니다. 특히 객체가 서브 클래 싱되거나 다른 객체가 해당 속성을 관찰하는 경우가 있습니다.

(8) 결코 dealloc (dealloc 메소드 내에서 [super dealloc] 제외)을 호출 할 수 없습니다. 다른 객체에 대한 소유권이있는 경우 release 또는 autorelease를 호출하여 소유권을 양도해야합니다. 그런 다음 시스템은 적절한 경우 오브젝트에 대해 dealloc을 호출합니다. 하지만 당신은 절대 자신을 dealloc이라고 부르지 않습니다. memory management rules (그 단 9 단락과 이해하는 것이 중요합니다)을 읽어보십시오.

+0

감사합니다. 누군가가 지적한 MM 규칙에 대한 링크를 발견했습니다. 아프다. –

+0

Btw, 이러한 모든 질문에 대한 내 아이디어를 공개하고 예기치 않은 충돌 (응용 프로그램이 충돌 후 nil에 대한 참조를 설정 한 후 산산조각이 때. 왜 지구상에서 nil에 대한 포인터를 할당하면 응용 프로그램이 중단됩니까? 그때부터 나는 '자기'를 사용하여 어디서나 다른 참조에 대한 포인터를 할당하고 있습니다. –

+0

참조가 유효하지 않거나 할당 취소 된 객체의 일부인 경우 nil에 대한 참조를 설정하는 유일한 이유는 충돌합니다. NSZombies를 활성화하면 도움이 될 것입니다. –

0

확인. B를 nil로 설정하지 않으면 트릭을 수행하지 않는다는 것을 확인했습니다. 그래서 B 컨트롤러를 만들 때 (탐색하고 싶을 때) nil을 확인하지 않습니다.

대신, 난 다음 내가 A의 viewDidAppear 방법에서, 나는이 스레드는 현재 닫혀 생각

B.

을 해제, 그리고 컨트롤러를 만들고 B. 에 할당, B를 놓습니다. 감사!

0

A4) 유형이 다릅니다. 그들은 모두 0이지만 NULL은 void *이고 nil은 id이며 Nil은 클래스 포인터입니다.