Skip to content

Commit

Permalink
[iOS] Improve background layer frame mapping performance
Browse files Browse the repository at this point in the history
  • Loading branch information
albyrock87 committed Sep 25, 2024
1 parent 2a50f12 commit 9d24253
Show file tree
Hide file tree
Showing 16 changed files with 163 additions and 17 deletions.
1 change: 0 additions & 1 deletion src/Compatibility/Core/src/iOS/Renderers/FrameRenderer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,6 @@ public override void LayoutSubviews()
if (_previousSize != Bounds.Size)
{
SetNeedsDisplay();
this.UpdateBackgroundLayer();
}

base.LayoutSubviews();
Expand Down
3 changes: 0 additions & 3 deletions src/Compatibility/Core/src/iOS/Renderers/PageRenderer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -135,9 +135,6 @@ public override void ViewDidLayoutSubviews()

if (_safeAreasSet || !Forms.IsiOS11OrNewer)
UpdateUseSafeArea();

if (Element.Background != null && !Element.Background.IsEmpty)
NativeView?.UpdateBackgroundLayer();
}

[SupportedOSPlatform("ios11.0")]
Expand Down
5 changes: 0 additions & 5 deletions src/Compatibility/Core/src/iOS/VisualElementRenderer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -252,11 +252,6 @@ public override void LayoutSubviews()
if (_blur.Superview == null)
Superview.Add(_blur);
}

bool hasBackground = Element?.Background != null && !Element.Background.IsEmpty;

if (hasBackground)
NativeView.UpdateBackgroundLayer();
}

#else
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,6 @@ public override void LayoutSubviews()
if (_previousSize != Bounds.Size)
{
SetNeedsDisplay();
this.UpdateBackgroundLayer();
}

base.LayoutSubviews();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,8 @@ public static void InsertBackgroundLayer(this CALayer layer, CALayer backgroundL
layer.InsertSublayer(backgroundLayer, index);
else
layer.AddSublayer(backgroundLayer);

(backgroundLayer as IAutoSizableCALayer)?.AutoSizeToSuperLayer();
}
}

Expand Down Expand Up @@ -176,6 +178,7 @@ public static void RemoveBackgroundLayer(this CALayer layer)
}
}

[Obsolete("MAUI background layers now automatically update their Frame when their SuperLayer Frame changes. This method will be removed in a future release.")]
public static void UpdateBackgroundLayer(this UIView view) =>
view.UpdateBackgroundLayerFrame(BackgroundLayer);

Expand Down
1 change: 0 additions & 1 deletion src/Core/src/Handlers/View/ViewHandler.iOS.cs
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,6 @@ internal static void MapContextFlyout(IElementHandler handler, IContextFlyoutEle
static partial void MappingFrame(IViewHandler handler, IView view)
{
UpdateTransformation(handler, view);
handler.ToPlatform().UpdateBackgroundLayerFrame();
}

public static void MapTranslationX(IViewHandler handler, IView view)
Expand Down
1 change: 0 additions & 1 deletion src/Core/src/Platform/iOS/ContentView.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ public override void LayoutSubviews()
base.LayoutSubviews();

UpdateClip();
this.UpdateBackgroundLayerFrame();
}

internal IBorderStroke? Clip
Expand Down
13 changes: 13 additions & 0 deletions src/Core/src/Platform/iOS/IAutoSizableCALayer.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
namespace Microsoft.Maui.Platform
{
/// <summary>
/// Provides a way to automatically size a CALayer to its super layer.
/// </summary>
public interface IAutoSizableCALayer
{
/// <summary>
/// Automatically sizes the CALayer to its super layer.
/// </summary>
void AutoSizeToSuperLayer();
}
}
2 changes: 2 additions & 0 deletions src/Core/src/Platform/iOS/LayerExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ public static void InsertBackgroundLayer(this UIView control, CALayer background
layer.InsertSublayer(backgroundLayer, index);
else
layer.AddSublayer(backgroundLayer);

(backgroundLayer as IAutoSizableCALayer)?.AutoSizeToSuperLayer();
}
}

Expand Down
33 changes: 31 additions & 2 deletions src/Core/src/Platform/iOS/MauiCALayer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,14 @@
using System.Diagnostics.CodeAnalysis;
using CoreAnimation;
using CoreGraphics;
using Foundation;
using Microsoft.Maui.Graphics;
using Microsoft.Maui.Graphics.Platform;
using UIKit;

namespace Microsoft.Maui.Platform
{
public class MauiCALayer : CALayer
public class MauiCALayer : CALayer, IAutoSizableCALayer
{
CGRect _bounds;
[UnconditionalSuppressMessage("Memory", "MEM0002", Justification = "IShape is a non-NSObject in MAUI.")]
Expand All @@ -30,13 +31,41 @@ public class MauiCALayer : CALayer

nfloat _strokeMiterLimit;

[UnconditionalSuppressMessage("Memory", "MEM0002", Justification = "Sublayer already holds a reference to SuperLayer by design.")]
IDisposable? _boundsObserver;

public MauiCALayer()
{
_bounds = new CGRect();

ContentsScale = UIScreen.MainScreen.Scale;
}

protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
_boundsObserver?.Dispose();
_boundsObserver = null;
}

public override void RemoveFromSuperLayer()
{
_boundsObserver?.Dispose();
_boundsObserver = null;
base.RemoveFromSuperLayer();
}

public void AutoSizeToSuperLayer()
{
var superLayer = SuperLayer ?? throw new InvalidOperationException("SuperLayer should be set before calling AutoSizeToSuperLayer");
_boundsObserver?.Dispose();
_boundsObserver = superLayer.AddObserver("bounds", NSKeyValueObservingOptions.New, _ =>
{
Frame = SuperLayer?.Bounds ?? CGRect.Empty;
});

Frame = superLayer.Bounds;
}

public override void AddAnimation(CAAnimation animation, string? key)
{
// Do nothing, we don't want animations here
Expand Down
35 changes: 34 additions & 1 deletion src/Core/src/Platform/iOS/StaticCAGradientLayer.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,42 @@
using System;
using System.Diagnostics.CodeAnalysis;
using CoreAnimation;
using CoreGraphics;
using Foundation;

namespace Microsoft.Maui.Platform;

class StaticCAGradientLayer : CAGradientLayer
class StaticCAGradientLayer : CAGradientLayer, IAutoSizableCALayer
{
[UnconditionalSuppressMessage("Memory", "MEM0002", Justification = "Sublayer already holds a reference to SuperLayer by design.")]
IDisposable? _boundsObserver;

protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
_boundsObserver?.Dispose();
_boundsObserver = null;
}

public override void RemoveFromSuperLayer()
{
_boundsObserver?.Dispose();
_boundsObserver = null;
base.RemoveFromSuperLayer();
}

public void AutoSizeToSuperLayer()
{
var superLayer = SuperLayer ?? throw new InvalidOperationException("SuperLayer should be set before calling AutoSizeToSuperLayer");
_boundsObserver?.Dispose();
_boundsObserver = superLayer.AddObserver("bounds", NSKeyValueObservingOptions.New, _ =>
{
Frame = SuperLayer?.Bounds ?? CGRect.Empty;
});

Frame = superLayer.Bounds;
}

public override void AddAnimation(CAAnimation animation, string? key)
{
// Do nothing, we don't want animations here
Expand Down
35 changes: 34 additions & 1 deletion src/Core/src/Platform/iOS/StaticCALayer.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,42 @@
using System;
using System.Diagnostics.CodeAnalysis;
using CoreAnimation;
using CoreGraphics;
using Foundation;

namespace Microsoft.Maui.Platform;

class StaticCALayer : CALayer
class StaticCALayer : CALayer, IAutoSizableCALayer
{
[UnconditionalSuppressMessage("Memory", "MEM0002", Justification = "Sublayer already holds a reference to SuperLayer by design.")]
IDisposable? _boundsObserver;

protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
_boundsObserver?.Dispose();
_boundsObserver = null;
}

public override void RemoveFromSuperLayer()
{
_boundsObserver?.Dispose();
_boundsObserver = null;
base.RemoveFromSuperLayer();
}

public void AutoSizeToSuperLayer()
{
var superLayer = SuperLayer ?? throw new InvalidOperationException("SuperLayer should be set before calling AutoSizeToSuperLayer");
_boundsObserver?.Dispose();
_boundsObserver = superLayer.AddObserver("bounds", NSKeyValueObservingOptions.New, _ =>
{
Frame = SuperLayer?.Bounds ?? CGRect.Empty;
});

Frame = superLayer.Bounds;
}

public override void AddAnimation(CAAnimation animation, string? key)
{
// Do nothing, we don't want animations here
Expand Down
35 changes: 34 additions & 1 deletion src/Core/src/Platform/iOS/StaticCAShapeLayer.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,42 @@
using System;
using System.Diagnostics.CodeAnalysis;
using CoreAnimation;
using CoreGraphics;
using Foundation;

namespace Microsoft.Maui.Platform;

class StaticCAShapeLayer : CAShapeLayer
class StaticCAShapeLayer : CAShapeLayer, IAutoSizableCALayer
{
[UnconditionalSuppressMessage("Memory", "MEM0002", Justification = "Sublayer already holds a reference to SuperLayer by design.")]
IDisposable? _boundsObserver;

protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
_boundsObserver?.Dispose();
_boundsObserver = null;
}

public override void RemoveFromSuperLayer()
{
_boundsObserver?.Dispose();
_boundsObserver = null;
base.RemoveFromSuperLayer();
}

public void AutoSizeToSuperLayer()
{
var superLayer = SuperLayer ?? throw new InvalidOperationException("SuperLayer should be set before calling AutoSizeToSuperLayer");
_boundsObserver?.Dispose();
_boundsObserver = superLayer.AddObserver("bounds", NSKeyValueObservingOptions.New, _ =>
{
Frame = SuperLayer?.Bounds ?? CGRect.Empty;
});

Frame = superLayer.Bounds;
}

public override void AddAnimation(CAAnimation animation, string? key)
{
// Do nothing, we don't want animations here
Expand Down
2 changes: 2 additions & 0 deletions src/Core/src/Platform/iOS/ViewExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -248,9 +248,11 @@ public static void UpdateBorder(this UIView platformView, IView view)
public static T? FindDescendantView<T>(this UIView view) where T : UIView =>
FindDescendantView<T>(view, (_) => true);

[Obsolete("MAUI background layers now automatically update their Frame when their SuperLayer Frame changes. This method will be removed in a future release.")]
public static void UpdateBackgroundLayerFrame(this UIView view) =>
view.UpdateBackgroundLayerFrame(BackgroundLayerName);

[Obsolete("MAUI background layers now automatically update their Frame when their SuperLayer Frame changes. This method will be removed in a future release.")]
internal static void UpdateBackgroundLayerFrame(this UIView view, string layerName)
{
if (view.Frame.IsEmpty)
Expand Down
5 changes: 5 additions & 0 deletions src/Core/src/PublicAPI/net-ios/PublicAPI.Unshipped.txt
Original file line number Diff line number Diff line change
Expand Up @@ -61,3 +61,8 @@ static Microsoft.Maui.Platform.UIWindowExtensions.GetWindow(this UIKit.UIWindowS
static Microsoft.Maui.ViewExtensions.DisconnectHandlers(this Microsoft.Maui.IView! view) -> void
override Microsoft.Maui.Platform.MauiCALayer.AddAnimation(CoreAnimation.CAAnimation! animation, string? key) -> void
*REMOVED*override Microsoft.Maui.Handlers.BorderHandler.ConnectHandler(Microsoft.Maui.Platform.ContentView! platformView) -> void
Microsoft.Maui.Platform.IAutoSizableCALayer
Microsoft.Maui.Platform.IAutoSizableCALayer.AutoSizeToSuperLayer() -> void
Microsoft.Maui.Platform.MauiCALayer.AutoSizeToSuperLayer() -> void
override Microsoft.Maui.Platform.MauiCALayer.Dispose(bool disposing) -> void
override Microsoft.Maui.Platform.MauiCALayer.RemoveFromSuperLayer() -> void
Original file line number Diff line number Diff line change
Expand Up @@ -61,3 +61,8 @@ static Microsoft.Maui.Platform.UIWindowExtensions.GetWindow(this UIKit.UIWindowS
static Microsoft.Maui.ViewExtensions.DisconnectHandlers(this Microsoft.Maui.IView! view) -> void
override Microsoft.Maui.Platform.MauiCALayer.AddAnimation(CoreAnimation.CAAnimation! animation, string? key) -> void
*REMOVED*override Microsoft.Maui.Handlers.BorderHandler.ConnectHandler(Microsoft.Maui.Platform.ContentView! platformView) -> void
Microsoft.Maui.Platform.IAutoSizableCALayer
Microsoft.Maui.Platform.IAutoSizableCALayer.AutoSizeToSuperLayer() -> void
Microsoft.Maui.Platform.MauiCALayer.AutoSizeToSuperLayer() -> void
override Microsoft.Maui.Platform.MauiCALayer.Dispose(bool disposing) -> void
override Microsoft.Maui.Platform.MauiCALayer.RemoveFromSuperLayer() -> void

0 comments on commit 9d24253

Please sign in to comment.