2013-03-21 3 views
3

내 응용 프로그램에서 네트워킹이 필요한 개체에 대한 '인터넷 인식'기본 클래스가 있습니다. 인터넷 인식이 필요한 모든 객체가이 객체를 상속받습니다. 상상할 수 있듯이 많은 객체를 할당하고 할당을 해제합니다.Reachability Classes 충돌하는 프로그램 - 확실하지 않은 이유

인터넷 인식 기본 클래스에는 인터넷 상태를 확인하는 데 사용되는 도달 가능성 클래스와 상호 작용하는 다음 코드가 있습니다.

#import "Reachability.h" 

- (id) init { 
    ... 
    self.internetReachable = [Reachability reachabilityForInternetConnection]; 
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(checkNetworkStatus) name:kReachabilityChangedNotification object:nil]; 
    [self.internetReachable startNotifier]; 
    ... 
    } 
- (void) dealloc 
{ 
    [self.internetReachable stopNotifier]; 
    [[NSNotificationCenter defaultCenter] removeObserver:self]; 
} 

는 곧 내 응용 프로그램, 인터넷 상태에 변화가있는 한, 다음과 같은 오류와 응용 프로그램의 충돌 :

*** -[Reachability isKindOfClass:]: message sent to deallocated instance 0x1e249a30

필자의 다음 줄에 아래로 문제를 좀비 켜져 있고 추적 정지 NSNotifcations을 수신하고, 통지를 중지 넘어 Reachability.m

불행하게도
NSCAssert([(NSObject*) info isKindOfClass: [Reachability class]], @"info was wrong class in ReachabilityCallback"); 

내 코드, 메신저 내 개체가이 오류를 방지하기 위해 할 수있는 다른 확실하지.

도움이나 제안이 도움이 될 것입니다.

감사

VB

편집 : 할당 와 악기를 실행하고이이 수를 유지하는 역사였다 아래

OK 그렇게 대답의 조언을 다음과 같습니다.

enter image description here

은 내가, 내가 재단 (즉. NSNotifcationCenter)이 아니라 자신에 의해 호출되는 할당 해제 한 그 객체를 의심 같습니다.

내 인터넷 개체에 Reachability 개체에 대한 강력한 포인터가 있습니다. 할당이 해제되면 Reachability 객체도 할당 취소됩니다. 좀비가 Reachability 개체입니다. 내 인터넷 객체의 dealloc에서 removeObserver를 호출했지만 파운데이션은 여전히 ​​할당 해제 된 객체를 호출합니다. 이유를 이해할 수 없습니다 ...

답변

1

NSCAssert 라인은 할당 취소 된 오브젝트에 처음 액세스하는 곳입니다.하지만 오브젝트 라이프 사이클에 대해 더 알고 싶으면 Instruments를 사용해야합니다. Xcode의 프로파일 도구를 사용하여 시뮬레이터에서 할당 (누수가 아닌) 도구로 프로그램을 실행하십시오. 할당 도구의 실행 구성에서 Enable NSZombie Detection Record Reference Count를 설정합니다. NSCAssert 라인을 치면 Instruments는 좀비 정보 객체에 메시지를 보내고 그것을 기록하기위한 시도를 감지해야합니다. 좀비 정보 객체에 대한 자세한 정보를 살펴보면 인스트루먼트는 참조 카운트의 내역을 보여줄 것이므로 할당이 해제 된 시점을 확인할 수 있어야합니다.

+0

감사합니다. 답변을 올렸습니다. 어떤 아이디어? – Vazzyb

6

Reachability 개체가 생성 된 스레드와 다른 스레드에서 즉 할당 해제 되었기 때문에 Foundation이 아직 할당 취소 된 도달 가능성을 NSNotifcations로 보내는 이유는 그 때문입니다. 도달 가능성은 스레드로부터 안전하지 않습니다. Disachatch_async를 Reachability 객체가 생성 된 동일한 큐에 다시 사용하면 문제가 해결됩니다.

+0

아하, 기쁜 당신은 그것을 이해했다! –

+0

도움을 주셔서 감사합니다 – Vazzyb

2

이 작업은 Reachability 인스턴스를 생성하고 Reachability 인스턴스에 대한 참조를 보유하고있는 객체가 stopNotifier를 호출하지 않고 (또는 이전에) 할당을 해제 할 때 발생합니다!

매우 간단합니다. Reachability 인스턴스를 사용하여 스택에서 객체를 제거하기 전에 stopNotifier를 호출해야합니다. dealloc 메서드에서이 작업을 수행 할 수 있으며 viewController의 경우 viewDidDisappear 등과 같은 라이프 사이클 메서드 중 하나에서 호출 할 수 있습니다.

여기에 스레드를 넣을 필요가 없습니다. Reachability에서 startNotifier를 호출 할 때이 것은 Reachability의 설계에 의해 백그라운드 스레드에서 시작됩니다. 따라서 stopNotifier를 호출하면 스레딩을 처리합니다.

스레드를 망칠 필요가있는 이유는 Reachability에 대한 참조를 보유한 객체가 할당 해제되었지만 startNotifier에서 발생한 네트워크 변경 사항에 대해 등록 된 수신기 였기 때문입니다. 네트워크가 바뀌면, 당신의 객체는 아직 통지를 받기 위해 등록되어 있지만 어디에도 발견되지 않습니다. 충돌 사고. stopNotifier는 죽기 전에 모든 것을 등록 취소하고 모든 것이 좋다.

- (void)dealloc 
{ // self.hostReachability is my property holding my Reachability instance 
    if (self.hostReachability) { 
     [self.hostReachability stopNotifier]; 
    } 
} 
+0

위의 의견은 정말로 도움이되었습니다. 별도의 스레드에서 wifi 연결 가능성을 확인하고 서버에 연결하려고했습니다. 그 사이에 wifi가 멈 추면 앱이 충돌하여 * [Reachability isKindOfClass :] : 메시지가 할당 해제 된 인스턴스 0x1e249a30으로 전송되었습니다. 추가 중지 알림 및 응용 프로그램이 잘 작동합니다 .. 감사합니다 Logged –