Skip to content

Commit

Permalink
perf(macOS): Avoid calling Subviews getter inside Dispose
Browse files Browse the repository at this point in the history
  • Loading branch information
spouliot committed Jun 12, 2022
1 parent b8b5b04 commit eff8fd7
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,9 @@ private void ProcessType(INamedTypeSymbol typeSymbol)
builder.AppendLineInvariant($"using Windows.UI.Xaml;");
builder.AppendLineInvariant($"using Windows.UI.Xaml.Data;");
builder.AppendLineInvariant($"using Uno.Diagnostics.Eventing;");
builder.AppendLineInvariant("#if __MACOS__");
builder.AppendLineInvariant("using AppKit;");
builder.AppendLineInvariant("#endif");

using (builder.BlockInvariant($"namespace {typeSymbol.ContainingNamespace}"))
{
Expand Down Expand Up @@ -667,21 +670,27 @@ protected sealed override void Dispose(bool disposing)
// a native representation via the IntPtr ctor, particularly on iOS.
__Store?.Dispose();
#if __IOS__
var subviews = Subviews;
if (subviews.Length > 0)
{{
BinderCollector.RequestCollect();
#if __IOS__
foreach (var v in subviews)
{{
v.RemoveFromSuperview();
}}
}}
#elif __MACOS__
// avoids the managed array (and items) allocation(s) since we do not need them
if (this.GetSubviewsCount() > 0)
{{
BinderCollector.RequestCollect();
// avoids multiple native calls to remove subviews
Subviews = Array.Empty<AppKit.NSView>();
#endif
Subviews = Array.Empty<NSView>();
}}
#endif
base.Dispose(disposing);
Expand Down
31 changes: 29 additions & 2 deletions src/Uno.UI/Extensions/UIViewExtensions.iOSmacOS.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,16 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using Uno.UI.Extensions;
using Windows.UI.Xaml;
using Uno.Foundation.Logging;
using Uno.UI.Controls;

#if NET6_0_OR_GREATER
using ObjCRuntime;

#if !NET6_0_OR_GREATER
using NativeHandle = System.IntPtr;
#endif

#if XAMARIN_IOS_UNIFIED
Expand Down Expand Up @@ -687,5 +689,30 @@ public static void SetNeedsDisplay(this _View view)
view.NeedsDisplay = true;
#endif
}

#if __MACOS__
static readonly NativeHandle selSubviewsHandle = Selector.GetHandle("subviews");
#endif

[DllImport("/usr/lib/libobjc.dylib", EntryPoint="objc_msgSendSuper")]
private extern static NativeHandle NativeHandle_objc_msgSendSuper(NativeHandle receiver, IntPtr selector);

private static NativeHandle GetSubviewsHandle(this _View view)
{
#if __IOS__
return NativeHandle_objc_msgSendSuper(view.SuperHandle, Selector.GetHandle("subviews"));
#elif __MACOS__
return NativeHandle_objc_msgSendSuper(view.SuperHandle, selSubviewsHandle);
#endif
}

[DllImport("/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation")]
private extern static /* CFIndex */ nint CFArrayGetCount(/* CFArrayRef */ NativeHandle theArray);

internal static nint GetSubviewsCount(this _View view)
{
var handle = view.GetSubviewsHandle();
return CFArrayGetCount(handle);
}
}
}

0 comments on commit eff8fd7

Please sign in to comment.