Skip to content

Commit

Permalink
fix: Provide the ability to break on invalid calls to `NSObjectExtens…
Browse files Browse the repository at this point in the history
…ions.ValidateDispose`
  • Loading branch information
jeromelaban committed Nov 30, 2023
1 parent 4282cc9 commit 1359637
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 22 deletions.
6 changes: 6 additions & 0 deletions doc/articles/feature-flags.md
Original file line number Diff line number Diff line change
Expand Up @@ -102,3 +102,9 @@ It is also possible to adjust the delay in milliseconds (`Uno.UI.FeatureConfigur
## `ApplicationData`

On GTK and WPF it is possible to override the default `ApplicationData` folder locations using `WinRTFeatureConfiguration.ApplicationData` properties. For more information see [related docs here](/articles/features/applicationdata.md#data-location-on-gtk-and-wpf)

## Deprecated NSObjectExtensions.ValidateDispose for iOS

The method `NSObjectExtensions.ValidateDispose` is deprecated in Uno 5.x and will be removed in the next major release.

In order for calls to fail on uses of this method, set the `Uno.UI.FeatureConfiguration.UIElement.FailOnNSObjectExtensionsValidateDispose` flag to `true`.
53 changes: 31 additions & 22 deletions src/Uno.UI/Extensions/NSObjectExtensions.iOS.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,45 +6,54 @@
using Foundation;
using UIKit;
using CoreGraphics;
using Uno.UI;

namespace Foundation
{
public static class NSObjectExtensions
{
/// <summary>
/// Validates the call to the Dispose method.
/// THIS METHOD IS DEPRECATED. DO NOT USE IT.
/// It will be removed in the next major version.
/// </summary>
/// <param name="view">The view to be disposed.</param>
/// <param name="disposing">True if called from View.Dispose, False if called from the finalizer.</param>
/// <returns>True if the dispose method can continue executing, otherwise, false.</returns>
/// <remarks>This method will requeue the call to Dispose on the UIThread if called from the finalizer.</remarks>
/// <remarks>Validates the call to the Dispose method. This method will requeue the call to Dispose on the UIThread if called from the finalizer.</remarks>
public static bool ValidateDispose(this NSObject view, bool disposing)
{
if (!disposing)
if (FeatureConfiguration.UIElement.FailOnNSObjectExtensionsValidateDispose)
{
view.Log()
.ErrorFormat(
"The instance {0}/{1:X8} has not been disposed properly, re-scheduling. This usually indicates that the creator of this view did not dispose it properly.",
view.GetType(),
view.Handle
);
throw new InvalidOperationException($"NSObjectExtensions.ValidateDispose has been disabled. Remove any invocation to this method, it does not need to replaced by anything else.");
}
else
{
if (!disposing)
{
view.Log()
.ErrorFormat(
"The instance {0}/{1:X8} has not been disposed properly, re-scheduling. This usually indicates that the creator of this view did not dispose it properly.",
view.GetType(),
view.Handle
);

// Make sure the instance is kept alive
GC.ReRegisterForFinalize(view);
// Make sure the instance is kept alive
GC.ReRegisterForFinalize(view);

// We cannot execute the content of the dispose actions off of the UI Thread.
// So we reschedule the dispose on the UI Thread to avoid concurrency issues.
_ = CoreDispatcher.Main.RunIdleAsync(_ =>
{
// We cannot execute the content of the dispose actions off of the UI Thread.
// So we reschedule the dispose on the UI Thread to avoid concurrency issues.
_ = CoreDispatcher.Main.RunIdleAsync(_ =>
{
view.Dispose();
});
view.Dispose();
});

return false;
}
else
{
return true;
return false;
}
else
{
return true;
}
}
}
}
Expand Down
5 changes: 5 additions & 0 deletions src/Uno.UI/FeatureConfiguration.cs
Original file line number Diff line number Diff line change
Expand Up @@ -656,6 +656,11 @@ public static class UIElement
/// This defaults to false, which prevents the specific event instead of calling CompleteGesture
/// </summary>
public static bool DisablePointersSpecificEventPrevention { get; set; }

/// <summary>
/// Enables failure when <see cref="Foundation.NSObjectExtensions.ValidateDispose"/> is invoked.
/// </summary>
public static bool FailOnNSObjectExtensionsValidateDispose { get; set; }
}

public static class VisualState
Expand Down

0 comments on commit 1359637

Please sign in to comment.