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?
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With