5

MonoTouch에서 처리 할 때 코코아 객체에 대한 참조가 필요합니다. 그 이유는 ObjC 런타임이 여전히 개체에 대한 참조를 보유 할 수 있기 때문에 "MonoTouch 참조"가없는 경우 가비지 수집 될 수 있기 때문에 ObjC 런타임에서 액세스하려고하면 EXC_BAD_ACCESS이됩니다 .MonoTouch에서 UIViewController 해제하기/처리하기

두 개의 UIViewController 하위 클래스 인 VC1과 VC2가 있다고 가정 해보십시오. 사용자가 VC1의 버튼을 클릭하면 UI가 VC2로 이동하고 사용자가 앞뒤로 이동할 수 있습니다. 사용자가 탐색 할 때마다 VC2의 새 인스턴스를 만들면 이전 인스턴스에 대한 참조가 손실되어 다음 번에 didReceiveMemoryWarning이 UIViewController에 전파 될 때 가비지 수집되고 응용 프로그램이 중단됩니다.

이전 참조를 릴리스 할 수 있으므로 매번 동일한 VC2 인스턴스를 사용할 필요가 없습니다. Dispose이 충분하지 않은 것으로 보입니다.

답변

6

나는 그것을 이해하기 때문에 MonoTouch에서 다루는 코코아 개체에 대한 참조를 보유해야합니다.

아닙니다. MonoTouch 인스턴스는 네이티브 인스턴스에 대한 참조를 유지합니다. 인스턴스가 존재하는 한 네이티브 인스턴스가 살아있을 것입니다 (참조 카운트되고 MonoTouch가 참조를 해제하지 않기 때문에).

는 IOW는 MonoTouch 에 대한 참조를 유지하는 당신의 필요는 오랫동안 자신의 기본 부분이 필요로 인스턴스를 관리.

그 이유는 ObjC 런타임은 여전히, 그들이 쓰레기 수집 할 수 ... 객체에

기본을 참조를 보유 할 수 있다는 점이다 (목표 C) 인스턴스를 참조 계산되지 쓰레기 수집 . 네이티브 인스턴스는 참조 카운트이 0에 도달 할 때까지 해제되지 않습니다 (연관된 관리되는 인스턴스가있는 동안 발생하지 않음).

또한 기본 인스턴스는 다른 기본 인스턴스에 대한 참조를 보유 할 수 있습니다. 네이티브 인스턴스에는 모두 인스턴스가 있습니다.

ObjC 런타임에서 액세스하려고하면 EXC_BAD_ACCESS가됩니다.

적어도 이런 식으로는 발생하지 않습니다. OTOH 당신의 경우에 어떤 일이 일어나고 있는지 알려주지는 못합니다 (코드 및/또는 충돌을 보지 않고). 그들의 작업을 완료하기 전에 의심 당신은 폐기하고 (수동 또는되지 않음)

인스턴스를 관리. 여기 일이 일어날 수 있는지의 단순화입니다 :

  • 가 만든 MT.X 경우 (예를 들어,이 UIView을) 관리;
  • 네이티브 X (원시 참조 횟수 == 1)를 만들고 참조합니다.
  • 이벤트를 오버라이드 (또는 델리게이트 추가 ...) MT.X에서 'ViewWillUnload'(네이티브로 존재);
  • MT.X 인스턴스를 다른 (관리되는) 인스턴스에 할당합니다 (예 : UIViewController;
  • 네이티브UIViewController네이티브 X (원시 참조 횟수 == 2)에 대한 참조를 추가합니다.
  • 애플리케이션
  • 는 (예 null에 변수 또는 다른 인스턴스를 설정 됨) MT.X 인스턴스에 대한 참조를 갖는 정지 ... happilly 실행;
  • MT.X에 대한 참조가 없기 때문에 더 이상 가비지 콜렉터가 기본 X에 참조를 줄일 수있는 Dispose를 호출 인스턴스를 관리 처분합니다 (기본 참조 카운트 == 1). 그러나 네이티브 인스턴스는 뷰 컨트롤러에서 계속 참조 (0이 아닌)하므로 해제되지 않습니다.
  • UIViewController은 기본적으로 X.ViewWillUnload (예 : 새로운 UIView을로드하려고 시도 함)을 트리거합니다. X 이후
  • 은 여전히 ​​(참조 카운트 == 1) 기본적으로 존재하는 그것은 다시 로 이동를 배치 그 했다 ... 인스턴스를 관리하려고합니다 ViewWillUnload의 호출합니다.

이 문제에 대한 해결책은 보장 당신이 자신의 작업을 완료 한 자신의 기본 부분까지 인스턴스를 관리 처분하지 않을 수 있도록하는 것입니다.

+1

고맙습니다.하지만 참고할만한 내용이 없습니다. VC2를 참조하는 유일한 관리 대상은 내 'VC1' 인스턴스입니다. 따라서이 인스턴스를 null로 만들 때 원시 VC2 인스턴스의 참조 카운트는 0이어야합니다.하지만 iOS에서 컨트롤러는'didReceiveMemoryWarning' 메시지를 배포하기 위해'didReceiveMemoryWarning' 메시지가 나타나 자마자 내 앱이 충돌하기 때문입니다. – cheeesus

+0

** 관리 ** 참고 문헌이 없을 가능성이 있지만 ** 기본 ** 참조가 남아있을 수 있습니다 (부모 또는 부모간에). 폐기 된 (관리되는) 인스턴스로 다시 콜백 할 수 있기 때문에 라이프 사이클 (기본 측면)이 끝났음을 확신하기 전에 해당 인스턴스를 null로 설정해서는 안됩니다 (관리 측면). 작은 테스트 케이스가 있거나 추출 할 수있는 경우 버그 보고서 @ http://bugzilla.xamarin.com을 열고 코드를 검토합니다. – poupou

+0

좋아, 나는 그것을 격리하려고 노력하고있어. 당신의 도움을 주셔서 감사합니다. – cheeesus

1

내 앱에서 동일한 상황이 발생하고 GC에서 개체를 올바르게 수집합니다. 즉, VC에 대한 참조를 무효로하고 GC가 나머지를 처리하도록하는 문제는 결코 발생하지 않았습니다.

그러나 Dispose 메서드를 호출 할 때 문제가 발생했습니다. 우리는 이것을 수동으로해서는 안됩니다. 대신 GC가 객체를 수집하고 자원을 확보 할 때까지 기다려야합니다. 기본 NSObject 클래스는 finalizer에 Dispose에 대한 호출이 있으므로 개체가 수집 될 때 관리되지 않는 모든 리소스가 해제됩니다.

루트 VC의 DidReceiveMemoryWarning 방법 중 일부에서 GC.Collect을 호출 할 수도 있습니다.

관련 문제