Message sent to a deallocated instance

ios, memory-management, objective-c, opentok, xcode4

Solution

Closing the session from `viewWillDisappear()` works if you can determine for sure that the view is going to be popped, not pushed or hidden. Some answers suggest putting this code in `dealloc()`. Regarding those suggestions, Apple says,

You should try to avoid managing the lifetime of limited resources using dealloc.

So, here is how you can determine for sure that your view will get popped. `viewWillDisappear()` is called when the view is popped from the stack, or is otherwise pushed somewhere else. This is the easiest way to determine which, and then unpublish/disconnect if it is truly popped. You can test for this with `isMovingFromParentViewController`. Also, here is where you can remove specific observers.

- (void)viewWillDisappear:(BOOL)animated {
    [super viewWillDisappear:animated]

    // This is true if the view controller is popped
    if ([self isMovingFromParentViewController])
    {
        NSLog(@"View controller was popped");

        // Remove observer
        [[NSNotificationCenter defaultCenter] removeObserver:self.session];

        ...

        //dispatch_async(self.opentokQueue, ^{
            if(self.subscriber){
                [self.subscriber close];
                self.subscriber = nil;
            }

            if (self.publisher) {
                [self doUnpublish];
            }

            if (self.session) {
                [self.session disconnect];
                self.session = nil;
            }
            //});
            [self doCloseRoomId:self.room.roomId position:self.room.position];
    }
    else
    {
        NSLog(@"New view controller was pushed");
    }
}

Ref: Testing for Specific Kinds of View Transitions

Problem

Background: All my OpenTok methods are in one `ViewController` that gets pushed into view, like a typical Master/detail VC relationship. The detailVC connects you to a different room depending on your selection. When I press the back button to pop the view away, I get a crash (maybe 1 out of 7 times): ``` [OTMessenger setRumorPingForeground] message sent to deallocated instance xxxxx ``` or ``` [OTSession setSessionConnectionStatus:]: message sent to deallocated instance 0x1e1ee440 ``` I put my unpublish/disconnect methods in viewDidDisappear: ``` -(void)viewDidDisappear:(BOOL)animated{ //dispatch_async(self.opentokQueue, ^{ [self.session removeObserver:self forKeyPath:@"connectionCount"]; if(self.subscriber){ [self.subscriber close]; self.subscriber = nil; } if (self.publisher) { [self doUnpublish]; } if (self.session) { [self.session disconnect]; self.session = nil; } //}); [self doCloseRoomId:self.room.roomId position:self.room.position]; } ``` Here is a trace: Here is the DetailViewController on Github: link here How to reproduce: Make a selection from the MasterVC, that takes you into the DetailVC which immediately attempts to connect to a session and publish Go back to previous, MasterVC quickly, usually before the session has had an a chance to publish a stream Try this several times and eventually it will crash. If I slow down and allow the publisher a chance to connect and publish, it is less likely to cause a crash. Expected result: It should just disconnect from the session/unpublish and start a new session as I go back and forth between the Master/DetailVC's. Other: What is your device and OS version? iOS 6 What type of connectivity were you on? wifi Zombies Enabled? Yes ARC Enabled? Yes Delegates set to nil? Yes, as far as I know Any help solving this crash would be greatly appreciated. Perhaps I'm missing something basic that I just can't see. What seems to happen is that the OTSession object in the OpenTok library continues to to send messages to objects in that library that have since been deallocated by switching views. The library has a [session disconnect] method that works fine if you give it enough time, but it takes close to 2-3 seconds, and that's a long time to pause an app between views. This might be a stupid question, but: Is there anyway to stop all processes initiated by a certain VC?

Original source

Related problems