Skip to content

Commit eff8fd7

Browse files
committed
perf(macOS): Avoid calling Subviews getter inside Dispose
1 parent b8b5b04 commit eff8fd7

File tree

2 files changed

+41
-5
lines changed

2 files changed

+41
-5
lines changed

src/SourceGenerators/Uno.UI.SourceGenerators/DependencyObject/DependencyObjectGenerator.cs

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,9 @@ private void ProcessType(INamedTypeSymbol typeSymbol)
157157
builder.AppendLineInvariant($"using Windows.UI.Xaml;");
158158
builder.AppendLineInvariant($"using Windows.UI.Xaml.Data;");
159159
builder.AppendLineInvariant($"using Uno.Diagnostics.Eventing;");
160+
builder.AppendLineInvariant("#if __MACOS__");
161+
builder.AppendLineInvariant("using AppKit;");
162+
builder.AppendLineInvariant("#endif");
160163

161164
using (builder.BlockInvariant($"namespace {typeSymbol.ContainingNamespace}"))
162165
{
@@ -667,21 +670,27 @@ protected sealed override void Dispose(bool disposing)
667670
// a native representation via the IntPtr ctor, particularly on iOS.
668671
__Store?.Dispose();
669672
673+
#if __IOS__
670674
var subviews = Subviews;
671675
672676
if (subviews.Length > 0)
673677
{{
674678
BinderCollector.RequestCollect();
675-
#if __IOS__
676679
foreach (var v in subviews)
677680
{{
678681
v.RemoveFromSuperview();
679682
}}
683+
}}
680684
#elif __MACOS__
685+
// avoids the managed array (and items) allocation(s) since we do not need them
686+
if (this.GetSubviewsCount() > 0)
687+
{{
688+
BinderCollector.RequestCollect();
689+
681690
// avoids multiple native calls to remove subviews
682-
Subviews = Array.Empty<AppKit.NSView>();
683-
#endif
691+
Subviews = Array.Empty<NSView>();
684692
}}
693+
#endif
685694
686695
base.Dispose(disposing);
687696

src/Uno.UI/Extensions/UIViewExtensions.iOSmacOS.cs

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,16 @@
44
using System;
55
using System.Collections.Generic;
66
using System.Linq;
7+
using System.Runtime.InteropServices;
78
using System.Text;
89
using Uno.UI.Extensions;
910
using Windows.UI.Xaml;
1011
using Uno.Foundation.Logging;
1112
using Uno.UI.Controls;
12-
13-
#if NET6_0_OR_GREATER
1413
using ObjCRuntime;
14+
15+
#if !NET6_0_OR_GREATER
16+
using NativeHandle = System.IntPtr;
1517
#endif
1618

1719
#if XAMARIN_IOS_UNIFIED
@@ -687,5 +689,30 @@ public static void SetNeedsDisplay(this _View view)
687689
view.NeedsDisplay = true;
688690
#endif
689691
}
692+
693+
#if __MACOS__
694+
static readonly NativeHandle selSubviewsHandle = Selector.GetHandle("subviews");
695+
#endif
696+
697+
[DllImport("/usr/lib/libobjc.dylib", EntryPoint="objc_msgSendSuper")]
698+
private extern static NativeHandle NativeHandle_objc_msgSendSuper(NativeHandle receiver, IntPtr selector);
699+
700+
private static NativeHandle GetSubviewsHandle(this _View view)
701+
{
702+
#if __IOS__
703+
return NativeHandle_objc_msgSendSuper(view.SuperHandle, Selector.GetHandle("subviews"));
704+
#elif __MACOS__
705+
return NativeHandle_objc_msgSendSuper(view.SuperHandle, selSubviewsHandle);
706+
#endif
707+
}
708+
709+
[DllImport("/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation")]
710+
private extern static /* CFIndex */ nint CFArrayGetCount(/* CFArrayRef */ NativeHandle theArray);
711+
712+
internal static nint GetSubviewsCount(this _View view)
713+
{
714+
var handle = view.GetSubviewsHandle();
715+
return CFArrayGetCount(handle);
716+
}
690717
}
691718
}

0 commit comments

Comments
 (0)