Bug 6270 - InvalidCastException in UITableViewCell.get_ImageView
Summary: InvalidCastException in UITableViewCell.get_ImageView
Status: RESOLVED NORESPONSE
Alias: None
Product: iOS
Classification: Xamarin
Component: General ()
Version: 5.3.x
Hardware: Macintosh Mac OS
: --- normal
Target Milestone: Untriaged
Assignee: Bugzilla
URL:
Depends on:
Blocks:
 
Reported: 2012-07-25 08:05 UTC by Paul DB
Modified: 2013-12-05 18:34 UTC (History)
2 users (show)

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

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 NORESPONSE

Description Paul DB 2012-07-25 08:05:03 UTC
I've been on a stability crusade with my iOS app for the past week and still cannot shake InvalidCastExceptions that crop up after my app has loaded a number of screens.
There doesn't seem to be a case to duplicate as such, but the issue is occurring fairly regularly after I've tested the app continuously for a while.

I am quite sure that its not the obvious cause of such an exception, given the issue is happening at UIKit level.

Googling has led me to believe it's probably some kind of GC issue.  My app does use background threading quite a lot to process various stuff, but I've been careful keep UI stuff on the UI thread.

I use MonoTouch.Dialog pretty extensively and mainly through custom subclass elements of my own creation. 

Below are 3 separate examples of the issue.  
The last two issues have not recurred since adding class level references to the UITableViewCell in my custom Dialog subclasses.
However the first issue below is still occurring regularly.

I'm running MonoTouch 5.3.5, using SGen and have turned on Reference Counting in an attempt to avoid GC issues.
Most of my testing is on device - an iPad 3.

InvalidCastException: Cannot cast from source type to destination type.
  at MonoTouch.UIKit.UITableViewCell.get_ImageView () [0x00030] in /Developer/MonoTouch/Source/monotouch/src/UIKit/UITableViewCell.g.cs:215 
  at MonoTouch.Dialog.StyledStringElement.PrepareCell (MonoTouch.UIKit.UITableViewCell cell) [0x00000] in <filename unknown>:0 
  at TapTo.IOS.UI.BaseStringElement.GetCell (MonoTouch.UIKit.UITableView tv) [0x00083] in /MYAPP/CustomElements/BaseStringElement.cs:92 
  at MonoTouch.Dialog.DialogViewController+Source.GetCell (MonoTouch.UIKit.UITableView tableView, MonoTouch.Foundation.NSIndexPath indexPath) [0x00000] in <filename unknown>:0 
  at MonoTouch.UIKit.UIApplication.Main (System.String[] args, System.String principalClassName, System.String delegateClassName) [0x0004c] in /Developer/MonoTouch/Source/monotouch/src/UIKit/UIApplication.cs:38 
  at TapToIOS.Application.Main (System.String[] args) [0x00027] in /MYAPP/Main.cs:26 


InvalidCastException: Cannot cast from source type to destination type. 
at MonoTouch.UIKit.UITableViewCell.get_TextLabel () [0x00000] in :0 
at MonoTouch.Dialog.StyledStringElement.PrepareCell (MonoTouch.UIKit.UITableViewCell cell) [0x00000] in :0 
at MYAPP.BaseStringElement.GetCell (MonoTouch.UIKit.UITableView tv) [0x00000] in :0 
at MonoTouch.Dialog.DialogViewController+Source.GetCell (MonoTouch.UIKit.UITableView tableView, MonoTouch.Foundation.NSIndexPath indexPath) [0x00000] in :0 
at MonoTouch.UIKit.UIApplication.Main (System.String[] args, System.String principalClassName, System.String delegateClassName) [0x00000] in :0 
at MYAPP.Application.Main (System.String[] args) [0x00000] in :0

InvalidCastException: Cannot cast from source type to destination type. 
at MonoTouch.Foundation.NSIndexPath.FromRowSection (Int32 row, Int32 section) [0x00000] in /Developer/MonoTouch/Source/monotouch/src/Foundation/NSIndexPath.g.cs:152 
at MonoTouch.Dialog.Element.get_IndexPath () [0x00000] in :0 
at MYAPP.FillHeightElement.GetHeight (MonoTouch.UIKit.UITableView tableView, MonoTouch.Foundation.NSIndexPath indexPath) [0x00053] in /MYAPP/FillHeightElement.cs:43 
at MonoTouch.Dialog.DialogViewController+SizingSource.GetHeightForRow (MonoTouch.UIKit.UITableView tableView, MonoTouch.Foundation.NSIndexPath indexPath) [0x00000] in :0 
at MonoTouch.UIKit.UITableView.ReloadData () [0x0000b] in /Developer/MonoTouch/Source/monotouch/src/UIKit/UITableView.g.cs:166 
at MonoTouch.Dialog.DialogViewController.ReloadData () [0x00000] in :0 
at MonoTouch.Dialog.DialogViewController.set_Root (MonoTouch.Dialog.RootElement value) [0x00000] in :0 
at MYAPP.ShowView (MonoTouch.Dialog.RootElement newView) [0x00119] 
at MYAPP.m__49 () [0x00007] 
at MonoTouch.Foundation.NSActionDispatcher.Apply () [0x00000
Comment 1 Rolf Bjarne Kvinge [MSFT] 2012-07-25 11:42:34 UTC
Can you turn on verbose cast messages?

You can do this by setting the MONO_DEBUG environment variable to 'casts' in the project's options, like this: http://screencast.com/t/d94gnFAEh

Now run again, and the exception message will tell you which type it is trying to convert from.
Comment 2 Paul DB 2012-07-26 06:34:45 UTC
Followed your instructions, but doesn't seem like having the MONO_DEBUG casts option made a difference when running in Debug | iPhone mod - I got the exact same exception trace as the get_ImageView one above.

However I then ran on the simulator and after abusing the app for a couple of minutes (repetitively opening/closing a lot of screens), I got another InvalidCastException. This one I have also seen before but is rarer.  Seems the MONO_DEBUG worked on the Simulator.

The LoadingView referred to below is an progress overlay that I put up when something is loading and I need to block input.
Below is the code that creates and attaches the LoadingView onto the current displayed View.
This code is always invoked on the UIThread via InvokeOnMainThread().
Looking below I can see I am not holding a class level reference to the rootView variable below...I suspect this is getting garbage collected occasionally, which could be causing the issue when I come to fade the LoadingView out and remove it from the rootView.

_loadingView = new LoadingView (message, bounds);
// because DialogViewController is a UITableViewController,
// we need to step OVER the UITableView, otherwise the loadingOverlay
// sits *in* the scrolling area of the table
var rootView = UIApplication.SharedApplication.Windows[0].RootViewController.View;
rootView.Add (_loadingView);
rootView.BringSubviewToFront (_loadingView);
rootView.UserInteractionEnabled = false;

MONO_DEBUG stacktrace below:

2012-07-26 20:21:32.397 MYAPPIOS[654:d0b] InvalidCastException: Unable to cast object of type 'MYAPP.IOS.UI.LoadingView' to type 'MonoTouch.Foundation.NSIndexPath'.
  at MonoTouch.Foundation.NSIndexPath.FromRowSection (Int32 row, Int32 section) [0x00000] in /Developer/MonoTouch/Source/monotouch/src/Foundation/NSIndexPath.g.cs:149 
  at MonoTouch.Dialog.Element.get_IndexPath () [0x00000] in <filename unknown>:0 
  at MYAPP.IOS.UI.FillHeightElement.GetHeight (MonoTouch.UIKit.UITableView tableView, MonoTouch.Foundation.NSIndexPath indexPath) [0x00053] in /MYAPP/UI/CustomElements/FillHeightElement.cs:45 
  at MonoTouch.Dialog.DialogViewController+SizingSource.GetHeightForRow (MonoTouch.UIKit.UITableView tableView, MonoTouch.Foundation.NSIndexPath indexPath) [0x00000] in <filename unknown>:0 
  at (wrapper managed-to-native) MonoTouch.ObjCRuntime.Messaging:void_objc_msgSend (intptr,intptr)
  at MonoTouch.UIKit.UITableView.ReloadData () [0x00008] in /Developer/MonoTouch/Source/monotouch/src/UIKit/UITableView.g.cs:161 
  at MonoTouch.Dialog.DialogViewController.ReloadData () [0x00000] in <filename unknown>:0 
  at MonoTouch.Dialog.DialogViewController.set_Root (MonoTouch.Dialog.RootElement value) [0x00000] in <filename unknown>:0 
  at MYAPP.IOS.Screens.FormEntryTable.ShowView (MonoTouch.Dialog.RootElement newView) [0x00119] in /MYAPP/Screens/Common/FormEntryScreen.cs:470 
  at MYAPP.IOS.Screens.FormEntryTable.<ViewModel_PropertyChanged>m__4A () [0x00007] in /MYAPP/Screens/Common/FormEntryScreen.cs:244 
  at MonoTouch.Foundation.NSActionDispatcher.Apply () [0x00000] in /Developer/MonoTouch/Source/monotouch/src/shared/Foundation/NSAction.cs:50 
  at (wrapper managed-to-native) MonoTouch.ObjCRuntime.Messaging:void_objc_msgSend_intptr_intptr_bool (intptr,intptr,intptr,intptr,bool)
  at MonoTouch.Foundation.NSObject.InvokeOnMainThread (MonoTouch.Foundation.NSAction action) [0x00007] in /Developer/MonoTouch/Source/monotouch/src/Foundation/NSObject.cs:290 
  at MYAPP.IOS.Screens.FormEntryTable.ViewModel_PropertyChanged (System.Object sender, System.ComponentModel.PropertyChangedEventArgs e) [0x00029] in /MYAPP/Screens/Common/FormEntryScreen.cs:241 
  at MYAPP.Mobile.Core.NotifyBase.RaisePropertyChanged (System.String propertyName) [0x0000d] in /MYAPP.Mobile/Core/NotifyBase.cs:70 
  at MYAPP.Mobile.ViewModels.ViewModelBase`1[MYAPP.Mobile.Models.FormEntry].RaisePropertyChanged (System.String propertyName) [0x0001c] in /MYAPP.Mobile/ViewModels/ViewModelBase.cs:131 
  at MYAPP.Mobile.ViewModels.FormEntryVM.ShowView (FormAnimation animationType) [0x00033] in /MYAPP.Mobile/ViewModels/FormEntryVM.cs:876 
  at MYAPP.Mobile.ViewModels.FormEntryVM.NextView_Execute (System.Object parameter) [0x000a3] in /MYAPP.Mobile/ViewModels/FormEntryVM.cs:312 
  at MYAPP.Mobile.ViewModels.FormEntryVM.Repeat_Execute (System.Object parameter) [0x00041] in /MYAPP.Mobile/ViewModels/FormEntryVM.cs:617 
  at MYAPP.Mobile.Core.DelegateCommand.Execute (System.Object parameter) [0x00000] in /MYAPP.Mobile/Core/DelegateCommand.cs:50 
  at MYAPP.IOS.Screens.FormEntryTable.<CreateRepeatDialog>m__4E (System.Object o, MonoTouch.UIKit.UIButtonEventArgs e) [0x00026] in /MYAPP/Screens/Common/FormEntryScreen.cs:507 
  at MonoTouch.UIKit.UIAlertView+_UIAlertViewDelegate.Clicked (MonoTouch.UIKit.UIAlertView alertview, Int32 buttonIndex) [0x00012] in /Developer/MonoTouch/Source/monotouch/src/UIKit/UIAlertView.g.cs:404 
  at (wrapper managed-to-native) MonoTouch.UIKit.UIApplication:UIApplicationMain (int,string[],intptr,intptr)
  at MonoTouch.UIKit.UIApplication.Main (System.String[] args, System.String principalClassName, System.String delegateClassName) [0x0004c] in /Developer/MonoTouch/Source/monotouch/src/UIKit/UIApplication.cs:38 
  at MYAPPIOS.Application.Main (System.String[] args) [0x00027] in /MYAPP/Main.cs:26
Comment 3 Rolf Bjarne Kvinge [MSFT] 2012-07-26 07:06:47 UTC
This very strange, this should definitively not happen. Can I get access to your app somehow so I can try it out myself?
Comment 4 Paul DB 2012-07-26 07:17:06 UTC
Hmm...could you sign a non-disclosure agreement?

I would have to give you pretty much the entire app source code, so would be a little nervous about having that going outside my company.
Comment 6 Paul DB 2012-07-31 19:58:56 UTC
Have sent the NDA to Xamarin support, heard nothing back.  Any news on this?
I'm hitting more of these kinds of errors.  It's probably because of poor code on my part, but I can't fix what I don't know :)
Comment 7 Paul DB 2012-08-02 09:15:52 UTC
Hi, just an update on this issue - I believe I have solved the problem.

I am using an MVVM pattern since my code base is heavily cross-platform (iOS/Android/WP).
Due to my previous experience with WPF and Silverlight, I have implemented a rudimentary data-binding approach on both iOS and Android in order to maximise MVVM based reuse.

As part of this, my binding classes were invoking ViewModel property sets/gets and commands on background threads through the use of ThreadPool.QueueUserWorkItem.  Then when the VM's PropertyChange and CollectionChange events were intercepted by my binding layer, I was running the View calls inside InvokeOnMainThread() lambdas.

While debugging I began watching the call stack and noticed there were regular occurrences of nested background thread to main thread to background thread (likely a different background thread) to main thread etc type call stacks building up through the data binding interactions.

Since I was really only running VM calls on background threads due to previous conventions learned from WPF/Silverlight, I went through and removed most of my ThreadPool.Queue calls but left the InvokeOnMainThread calls in place.
I still have background threading for download/upload stuff along with select places where screen loads are a few secs and I'd rather throw up a loading screen while code crunches in the background.
But generally there is nothing like the nested background to main thread stuff going on anymore, and there's been no noticeable degradation of app responsiveness.

My testing since making these changes has yet to turn up another InvalidCastException like those reported above.  I may be speaking too soon and more testing is needed, but all my usual means of duplicating the issue have yet to turn up the exception since the changes.

So if you would still like to see my code, I can sign the MNDA sent through to me, otherwise I guess you could try to investigate why things go pear shaped after a number of nested background to main and background again type daisy chains occur in MonoTouch.
Comment 8 Rolf Bjarne Kvinge [MSFT] 2012-08-06 13:58:14 UTC
Yes, I'd definitively like to figure out what's going on here.
Comment 9 Paul DB 2012-08-06 20:16:31 UTC
Some more info, the InvalidCasts came back at least in some limited scenarios even after the above threading changes I made.

Each time it occurred, the error seemed to always be casting incorrectly to the LoadingView mentioned above, so I went through all my LoadingView code line by line and found a bug.  
Inside the main LoadingView code, I was calling AddSubView on the same UILabel twice.  This bug has been in there for a long time, but since I've removed it the InvalidCasts have disappeared - this is now after a few days of testing.

I'm in the middle of an App Store review now, but will get the MNDA sorted in a week or so and then send through my code for you to look over Rolf.
Comment 10 PJ 2013-11-19 17:04:00 UTC
This bug has been in the NEEDINFO state with no changes for the last 90 days. Can we put this back into the NEW or CONFIRMED state, or are we still awaiting response?

If there is no change in the status of this bug over the next two weeks, this bug will be marked as NORESPONSE.
Comment 11 Paul DB 2013-11-19 17:34:18 UTC
Not much has changed since my last response.  Feel free to close this bug.
Comment 12 PJ 2013-12-05 18:34:01 UTC
This bug has not been changed from the NEEDINFO state since my previous comment, marking as RESOLVED NORESPONSE.

Please feel free to REOPEN this bug at any time if you are still experiencing the issue. Please add the requested information and set the bug back to the NEW (or CONFIRMED) state.