Bug 2161 - ViewDidDisappear() gets called even though the UIViewController is already disposed
Summary: ViewDidDisappear() gets called even though the UIViewController is already di...
Status: RESOLVED FEATURE
Alias: None
Product: iOS
Classification: Xamarin
Component: Xamarin.iOS.dll ()
Version: 5.0
Hardware: Macintosh Mac OS
: --- normal
Target Milestone: Untriaged
Assignee: Bugzilla
URL:
Depends on:
Blocks:
 
Reported: 2011-11-22 15:10 UTC by René Ruppert
Modified: 2011-11-24 03:51 UTC (History)
3 users (show)

Tags:
Is this bug a regression?: ---
Last known good build:


Attachments
MD 2.8 project demonstrating the issue (1.45 MB, application/zip)
2011-11-22 15:10 UTC, René Ruppert
Details


Notice (2018-05-24): bugzilla.xamarin.com is now in read-only mode.

Please join us on Visual Studio Developer Community and in the Xamarin and Mono organizations on GitHub to continue tracking issues. Bugzilla will remain available for reference in read-only mode. We will continue to work on open Bugzilla bugs, copy them to the new locations as needed for follow-up, and add the new items under Related Links.

Our sincere thanks to everyone who has contributed on this bug tracker over the years. Thanks also for your understanding as we make these adjustments and improvements for the future.


Please create a new report on Developer Community or GitHub with your current version information, steps to reproduce, and relevant error messages or log files if you are hitting an issue that looks similar to this resolved bug and you do not yet see a matching new report.

Related Links:
Status:
RESOLVED FEATURE

Description René Ruppert 2011-11-22 15:10:35 UTC
Created attachment 934 [details]
MD 2.8 project demonstrating the issue

This bug has been submitted because Poupou thought maybe MT can work around this problem which propbably lies in iOS SDK 5.
See here: http://stackoverflow.com/q/8214903/304870

I have attached a demo project (MD 2.8).
It adds the view of one controller to the window.
Then it adds the view of another controller as sib view to the first controller's view.

There is a button. If pushed, the view of the second added controller is removed from superview and the second controller gets disposed.

If built with SDK 4.3 this works without problems.
If built with SDK 5 it crashes in ViewDidDisappear(). Reason: the method gets called after the controller has been disposed.
In SKD 4.3 the method does not get called at all.
Comment 1 Sebastien Pouliot 2011-11-22 16:08:07 UTC
Thanks for the sample!

I used the simulator / debug build and I get a green square on top of the red square. Clicking the button does not crash the application and a breakpoint on ViewDidDisappear shows it is not being called. 

I tried both the iOS 4.3 and iOS 5 iPad simulator (not tried, yet, with the iPad hardware since I'm debugging something else with it on the macbook air).

Which version of MonoTouch are you using ?
Comment 2 René Ruppert 2011-11-23 04:12:07 UTC
I'm on MT 5.0.2

Please note:

I go to PROJECT -> RemoveFromSuperview Options -> iPhone Build

In there I change the SDK version to 4.3 and it does NOT CRASH.
If I change it to 5.0 it DOES CRASH.

Verified on two Lion installations.

ShortLivingController(): ViewDidDisappear, Handle = 0
Stacktrace:

  at (wrapper managed-to-native) MonoTouch.ObjCRuntime.Messaging.void_objc_msgSendSuper_bool (intptr,intptr,bool) <IL 0x0002d, 0xffffffff>
  at MonoTouch.UIKit.UIViewController.ViewDidDisappear (bool) [0x00021] in /Developer/MonoTouch/Source/monotouch/src/UIKit/UIViewController.g.cs:240
  at RemoveFromSuperview.AppDelegate/ShortLivingController.ViewDidDisappear (bool) [0x0001d] in /Users/iBrainloop/Downloads/RemoveFromSuperview/RemoveFromSuperview/AppDelegate.cs:83
  at (wrapper runtime-invoke) <Module>.runtime_invoke_void__this___sbyte (object,intptr,intptr,intptr) <IL 0x00054, 0xffffffff>
  at (wrapper managed-to-native) MonoTouch.UIKit.UIApplication.UIApplicationMain (int,string[],intptr,intptr) <IL 0x0009f, 0xffffffff>
  at MonoTouch.UIKit.UIApplication.Main (string[],string,string) [0x00042] in /Developer/MonoTouch/Source/monotouch/src/UIKit/UIApplication.cs:29
  at RemoveFromSuperview.Application.Main (string[]) [0x00000] in /Users/iBrainloop/Downloads/RemoveFromSuperview/RemoveFromSuperview/Main.cs:16
  at (wrapper runtime-invoke) <Module>.runtime_invoke_void_object (object,intptr,intptr,intptr) <IL 0x00050, 0xffffffff>

Native stacktrace:

	0   RemoveFromSuperview                 0x000e1018 mono_handle_native_sigsegv + 408
	1   RemoveFromSuperview                 0x00011d9f mono_sigsegv_signal_handler + 351
	2   libsystem_c.dylib                   0x95d0f59b _sigtramp + 43
	3   ???                                 0xffffffff 0x0 + 4294967295
	4   ???                                 0x103d6eea 0x0 + 272461546
	5   ???                                 0x103d6e18 0x0 + 272461336
	6   ???                                 0x0d087c7c 0x0 + 218659964
	7   ???                                 0x0d087df5 0x0 + 218660341
	8   RemoveFromSuperview                 0x00011aef mono_jit_runtime_invoke + 1407
	9   RemoveFromSuperview                 0x0022011a mono_runtime_invoke + 170
	10  RemoveFromSuperview                 0x002ee535 monotouch_trampoline + 3381
	11  UIKit                               0x0236dfbf -[UIViewController _setViewAppearState:isAnimating:] + 158
	12  UIKit                               0x0236e3f1 -[UIViewController __viewDidDisappear:] + 136
	13  UIKit                               0x0236fa22 __64-[UIViewController viewDidMoveToWindow:shouldAppearOrDisappear:]_block_invoke_0573 + 44
	14  UIKit                               0x0236e730 -[UIViewController _executeAfterAppearanceBlock] + 55
	15  UIKit                               0x022b75ea _afterCACommitHandler + 302
	16  CoreFoundation                      0x012ab9ce __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 30
	17  CoreFoundation                      0x01242670 __CFRunLoopDoObservers + 384
	18  CoreFoundation                      0x0120e4f6 __CFRunLoopRun + 1174
	19  CoreFoundation                      0x0120ddb4 CFRunLoopRunSpecific + 212
	20  CoreFoundation                      0x0120dccb CFRunLoopRunInMode + 123
	21  GraphicsServices                    0x0489f879 GSEventRunModal + 207
	22  GraphicsServices                    0x0489f93e GSEventRun + 114
	23  UIKit                               0x022a6a9b UIApplicationMain + 1175
	24  ???                                 0x09ff895d 0x0 + 167741789
	25  ???                                 0x09ff7140 0x0 + 167735616
	26  ???                                 0x09ff6e38 0x0 + 167734840
	27  ???                                 0x09ff6f8e 0x0 + 167735182
	28  RemoveFromSuperview                 0x00011aef mono_jit_runtime_invoke + 1407
	29  RemoveFromSuperview                 0x0022011a mono_runtime_invoke + 170
	30  RemoveFromSuperview                 0x00222e51 mono_runtime_exec_main + 705
	31  RemoveFromSuperview                 0x00222061 mono_runtime_run_main + 929
	32  RemoveFromSuperview                 0x000ad6df mono_jit_exec + 239
	33  RemoveFromSuperview                 0x002f41ca main + 5194
	34  RemoveFromSuperview                 0x00003345 start + 53

=================================================================
Got a SIGSEGV while executing native code. This usually indicates
a fatal error in the mono runtime or one of the native libraries 
used by your application.
=================================================================
Comment 3 Sebastien Pouliot 2011-11-23 14:03:28 UTC
This is weird. The project you sent me was showing "5.0" (SDK). Rebuilding on "4.3" worked (as expected) but going back to "5.0" does reproduce the same error that you have. 

Some "default" must be changing somewhere...
Comment 4 Sebastien Pouliot 2011-11-23 14:57:45 UTC
Back to the original issue - just don't call Dispose and it will work in both 4.3 and 5.0 SDK.

Why? When you do so you're forcing things to be cleaned up before the "right" time (and even if other parts of the code still reference it). In iOS5 libraries (SDK) this still needs to be available when ViewDidDisappear will be called later.

Is the memory reclaimed ? yep. Add a finalizer to ShortLivingController to CWL something, e.g.

			~ShortLivingController ()
			{
				Console.WriteLine ("~ShortLivingController");
			}

and you'll see that setting the 'shortLivingController' field to null is enough (i.e. it's not referenced anymore, by your code, and will be disposed when no one else needs it and the GC collects it).

I'll try to download your attachment again and see why it worked for me initially... (could be an human error but I don't see how I could have managed it ;-)
Comment 5 Sebastien Pouliot 2011-11-23 15:20:28 UTC
note: human error for my original SDK version mismatch - I re-downloaded your project and it's using 4.3 for the SDK. I had 5.0 this morning (previous one) but do not recall changing it (only the simulator version - which does not change the SDK version, I tried ;-)
Comment 6 René Ruppert 2011-11-24 03:51:51 UTC
Okay, I'm fine with that. Thanks for analyzing it. It was just one of these things where you rub your eyes and wonder WTF? :-)