Xamarin.Forms MacOS: Cannot access a disposed object. Object name: 'FormsNSTextField'.

Created on 31 Oct 2018  Â·  16Comments  Â·  Source: xamarin/Xamarin.Forms

Description

Cannot access a disposed object.
Object name: 'FormsNSTextField'.
We have a very simple requirment.

GUI is navigated to a BaseControl via adding the BaseControl window as a Children to Grid ContentView.
We are trying to achieve a simple functionality of hiding the Entry box upon successful registration. But when registred, navigated to other menuitems and switching the applications , Main GUI Crashes of application crashes with the above error, if NotRegistered stack panel with Entry(eRegistrationBox) is set to IsVisibility = false from Code behind.

We are currently using 2 stackpanels like below in a ContentView which are upon navigation are added to Grid.Children after Clearing the calling Grid.Children.Clear()

<StackLayout>
                     
         <StackLayout x:Name="Registered" IsVisible="true">
                
                <Label Text="Product is registered"/> 
            
         </StackLayout> 
            
         <StackLayout x:Name="NotRegistered" IsVisible="false">
               
                <Label Text="Product is not registered" />
                <Entry  x:Name="eRegistrationBox" TextChanged="eRegistrationKey_TextChanged"/>
                         
                <controls:TextButton x:Name="tbRegister" Text="Register" Tapped="btnRegister_Tapped" /> 
            
          </StackLayout> 
       
</StackLayout>

When registered the NotRegistered stackpanel's visibility is hidden. and vice versa.

The issue only happens when Entry(eRegistrationBox) is shown first as a part of our logic of Un-Registered, then NotRegistered stack panel is set IsVisible =False from IsVisible = True. But if we run GUI with application already registered i.e. NotRegistered stackpanel is already set to IsVisible = false, the application doesn't crash.

Steps to Reproduce

  1. Entry is shown first with in a stackpanel (like shown above)
  2. StackPanel Visibility set to false
  3. Navigated to other tabs
  4. Applications switched
  5. Clicked on the GUI again. and it crashes

The crash happens when HandleWindowDidBecomeKey gets invoked, and accesses Window and CurrentEditor, which are now disposed as part of the current object.
at

void HandleWindowDidBecomeKey(object sender, EventArgs args)
{
    if (Window != null && CurrentEditor == Window.FirstResponder)
        FocusChanged?.Invoke(this, new BoolEventArgs(true));
}

after Disposing at

if (Window != null)
{
    Window.DidResignKey -= HandleWindowDidResignKey;
    Window.DidBecomeKey -= HandleWindowDidBecomeKey;
}

Additional Findings

We were able to find a workaround if we use Editor(eRegistrationBox) instead of Entry(eRegistrationBox) and stop using visibility part. So this rules out the problem of this being caused by navigation of tabs. Moreover, if we start using Editor(eRegistrationBox) and IsVisibility part the GUI Crashes.
3rdly. It gives an exception if we use Entry and dont use the Visibility properties too. in other words it gives exception anyways with Entry upon navigating to other BaseControls but works fine if we use Editor and donot use Visibility options

Expected Behavior

GUI runs smoothly.

Actual Behavior

GUI Crashes

Basic Information

  • Version with issue: 3.2.0.839982
  • IDE: Visual Studio For Mac 2017
4 help wanted high macOS bug up-for-grabs

Most helpful comment

I was able to cause a crash by selecting the Entry, switching to another tab, command-tabbing to another application and then back.

All 16 comments

Does this only happen on Mojave? Does it happen on High Sierra also? Looks similar to another recently fixed issue #4076 .

Nop it is currently happening on High Sierra and Mojave both. and I agree it does seems similar but our issue is a bit different in details. If you look at the additional information part. It works fine with Editor and without visibility part upon navigation. but with Entry it crashes everytime (with and without visibility)

I've reproduced this on Sierra.

It looks like a couple of events are intended to be unregistered during the dispose, however Window is already null, so the unregistration is skipped. BUT, the handlers still get called later. The crash happens when HandleWindowDidBecomeKey gets invoked, and accesses Window and CurrentEditor, which look to now be disposed as part of the current object.

The only way I've been able to work around this is to copy the EntryRenderer into my own code, and modify the HandleWindowDidResignKey and HandleWindowDidBecomeKey handlers to return immediately if _disposed is set. However, this is a pretty bad cludge, and the real fix would be to make sure those handlers don't get called in the first place.

I was able to cause a crash by selecting the Entry, switching to another tab, command-tabbing to another application and then back.

It looks like this issue may have been introduced with this commit, when the event handlers in question were added:
https://github.com/xamarin/Xamarin.Forms/commit/02050d7b6e25b93d0c13e62c06764f79245df55c#diff-6c0cb2c7530eb6279612f5c2aa615331

Guys is there an estimated time of fix for this issue? @ech0matrix @pauldipietro

@PureWeen @pauldipietro guys would be great if you can update on this please.. thanks

@PureWeen @pauldipietro
Are update here?

Doing another ping on this issue - still plaguing us

@PureWeen @samhouts @pauldipietro

Hellpp required on this one :-)
would be great if an ETA can be provided

Or at least a work around, as this causes the app to crash

I've reproduced this on Sierra.

It looks like a couple of events are intended to be unregistered during the dispose, however Window is already null, so the unregistration is skipped. BUT, the handlers still get called later. The crash happens when HandleWindowDidBecomeKey gets invoked, and accesses Window and CurrentEditor, which look to now be disposed as part of the current object.

The only way I've been able to work around this is to copy the EntryRenderer into my own code, and modify the HandleWindowDidResignKey and HandleWindowDidBecomeKey handlers to return immediately if _disposed is set. However, this is a pretty bad cludge, and the real fix would be to make sure those handlers don't get called in the first place.

Really not the way I want to get it working but it works and gives a workaround until Xamarin decides to fix the issue. Had to recreate quite a few classes to get the renderer copied in. Thanks!

Just seeing if there was any movement on this. I created a simple solution that easily reproduces the issue here. In this scenario, it happens when you click off the app and then back on to it.
The login page has two hidden Entry controls.
https://github.com/RadWes/XamTest
Can anyone share a sample of the work around?

Can anyone share a sample of the work around?

Here's the files I copied and modified to not call the events if the window is disposed like ech0matrix posted above.

https://gist.github.com/baywolf-studios/03caf8b9879d9ec6619a37e5e52a9671

probably some better way to organize and recreate them but... it seems to work.

Any updates on this getting fixed?

I'm interested in a fix for this also 😄

Was this page helpful?
0 / 5 - 0 ratings