Skip to content

Commit

Permalink
Make iOS StatusBarBehavior more robust and not throw exceptions (#2128)
Browse files Browse the repository at this point in the history
* Update StatusBar.ios.cs

* Rename to `TryUpdateStatusBarAppearance`

Since it it no longer guaranteed that the status bar will update we will prepend the method name with `Try` and return a `bool` noting its success.

We will also print to `Trace.WriteLine` the status when it fails

* Fix StatusBarBehaviorPage bug

---------

Co-authored-by: Brandon Minnick <[email protected]>
  • Loading branch information
jfversluis and brminnick authored Aug 18, 2024
1 parent f0f6059 commit 9cabfd1
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 45 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@
<Label Text="Red" />
<Slider
Margin="20,0"
Maximum="255"
Maximum="1"
MaximumTrackColor="Red"
Minimum="0"
MinimumTrackColor="Red"
Expand All @@ -96,7 +96,7 @@
<Label Text="Green" />
<Slider
Margin="20,0"
Maximum="255"
Maximum="1"
MaximumTrackColor="Green"
Minimum="0"
MinimumTrackColor="Green"
Expand All @@ -106,7 +106,7 @@
<Label Text="Blue" />
<Slider
Margin="20,0"
Maximum="255"
Maximum="1"
MaximumTrackColor="Blue"
Minimum="0"
MinimumTrackColor="Blue"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ public partial class StatusBarBehaviorViewModel : BaseViewModel
{
[ObservableProperty]
[NotifyPropertyChangedFor(nameof(StatusBarColor))]
int redSliderValue, greenSliderValue, blueSliderValue;
double redSliderValue, greenSliderValue, blueSliderValue;

[ObservableProperty]
[NotifyPropertyChangedFor(nameof(StatusBarColor))]
Expand Down
95 changes: 54 additions & 41 deletions src/CommunityToolkit.Maui.Core/Platform/StatusBar/StatusBar.ios.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Runtime.Versioning;
using System.Diagnostics;
using System.Runtime.Versioning;
using Microsoft.Maui.ApplicationModel;
using Microsoft.Maui.Platform;

Expand All @@ -7,10 +8,11 @@ namespace CommunityToolkit.Maui.Core.Platform;
[UnsupportedOSPlatform("MacCatalyst")]
static partial class StatusBar
{
static void PlatformSetColor(Color color)
/// <summary>
/// Method to update the status bar size.
/// </summary>
public static void UpdateBarSize()
{
var uiColor = color.ToPlatform();

if (OperatingSystem.IsIOSVersionAtLeast(13))
{
var statusBarTag = new IntPtr(38482);
Expand All @@ -23,12 +25,8 @@ static void PlatformSetColor(Color color)
continue;
}

// ReSharper disable once NullCoalescingConditionIsAlwaysNotNullAccordingToAPIContract
// window.ViewWithTag(tag) can return null
statusBar ??= new UIView(statusBarFrame.Value);
statusBar.Tag = statusBarTag;
statusBar.BackgroundColor = uiColor;
statusBar.TintColor = uiColor;
statusBar.Frame = UIApplication.SharedApplication.StatusBarFrame;
var statusBarSubViews = window.Subviews.Where(x => x.Tag == statusBarTag).ToList();
foreach (var statusBarSubView in statusBarSubViews)
Expand All @@ -38,41 +36,24 @@ static void PlatformSetColor(Color color)

window.AddSubview(statusBar);

UpdateStatusBarAppearance(window);
TryUpdateStatusBarAppearance(window);
}
}
else
{
if (UIApplication.SharedApplication.ValueForKey(new NSString("statusBar")) is UIView statusBar
&& statusBar.RespondsToSelector(new ObjCRuntime.Selector("setBackgroundColor:")))
if (UIApplication.SharedApplication.ValueForKey(new NSString("statusBar")) is UIView statusBar)
{
statusBar.BackgroundColor = uiColor;
statusBar.Frame = UIApplication.SharedApplication.StatusBarFrame;
}

UpdateStatusBarAppearance();
TryUpdateStatusBarAppearance();
}
}

static void PlatformSetStyle(StatusBarStyle statusBarStyle)
static void PlatformSetColor(Color color)
{
var uiStyle = statusBarStyle switch
{
StatusBarStyle.Default => UIStatusBarStyle.Default,
StatusBarStyle.LightContent => UIStatusBarStyle.LightContent,
StatusBarStyle.DarkContent => UIStatusBarStyle.DarkContent,
_ => throw new NotSupportedException($"{nameof(StatusBarStyle)} {statusBarStyle} is not yet supported on iOS")
};

UIApplication.SharedApplication.SetStatusBarStyle(uiStyle, false);

UpdateStatusBarAppearance();
}
var uiColor = color.ToPlatform();

/// <summary>
/// Method to update the status bar size.
/// </summary>
public static void UpdateBarSize()
{
if (OperatingSystem.IsIOSVersionAtLeast(13))
{
var statusBarTag = new IntPtr(38482);
Expand All @@ -85,8 +66,12 @@ public static void UpdateBarSize()
continue;
}

// ReSharper disable once NullCoalescingConditionIsAlwaysNotNullAccordingToAPIContract
// window.ViewWithTag(tag) can return null
statusBar ??= new UIView(statusBarFrame.Value);
statusBar.Tag = statusBarTag;
statusBar.BackgroundColor = uiColor;
statusBar.TintColor = uiColor;
statusBar.Frame = UIApplication.SharedApplication.StatusBarFrame;
var statusBarSubViews = window.Subviews.Where(x => x.Tag == statusBarTag).ToList();
foreach (var statusBarSubView in statusBarSubViews)
Expand All @@ -96,45 +81,73 @@ public static void UpdateBarSize()

window.AddSubview(statusBar);

UpdateStatusBarAppearance(window);
TryUpdateStatusBarAppearance(window);
}
}
else
{
if (UIApplication.SharedApplication.ValueForKey(new NSString("statusBar")) is UIView statusBar)
if (UIApplication.SharedApplication.ValueForKey(new NSString("statusBar")) is UIView statusBar
&& statusBar.RespondsToSelector(new ObjCRuntime.Selector("setBackgroundColor:")))
{
statusBar.Frame = UIApplication.SharedApplication.StatusBarFrame;
statusBar.BackgroundColor = uiColor;
}

UpdateStatusBarAppearance();
TryUpdateStatusBarAppearance();
}
}

static void UpdateStatusBarAppearance()
static void PlatformSetStyle(StatusBarStyle statusBarStyle)
{
var uiStyle = statusBarStyle switch
{
StatusBarStyle.Default => UIStatusBarStyle.Default,
StatusBarStyle.LightContent => UIStatusBarStyle.LightContent,
StatusBarStyle.DarkContent => UIStatusBarStyle.DarkContent,
_ => throw new NotSupportedException($"{nameof(StatusBarStyle)} {statusBarStyle} is not yet supported on iOS")
};

UIApplication.SharedApplication.SetStatusBarStyle(uiStyle, false);

TryUpdateStatusBarAppearance();
}

static bool TryUpdateStatusBarAppearance()
{
if (OperatingSystem.IsIOSVersionAtLeast(13))
{
var didUpdateAllStatusBars = true;

foreach (var window in UIApplication.SharedApplication.Windows)
{
UpdateStatusBarAppearance(window);
didUpdateAllStatusBars &= TryUpdateStatusBarAppearance(window);
}

return didUpdateAllStatusBars;
}
else
{
var window = UIApplication.SharedApplication.KeyWindow;
UpdateStatusBarAppearance(window);
return TryUpdateStatusBarAppearance(window);
}
}

static void UpdateStatusBarAppearance(UIWindow? window)
static bool TryUpdateStatusBarAppearance(UIWindow? window)
{
var vc = window?.RootViewController ?? WindowStateManager.Default.GetCurrentUIViewController() ?? throw new InvalidOperationException($"{nameof(window.RootViewController)} cannot be null");
var vc = window?.RootViewController ?? WindowStateManager.Default.GetCurrentUIViewController();

if (vc is null)
{
Trace.WriteLine("Unable to update Status Bar Appearance because Current UIViewController is null");
return false;
}

while (vc.PresentedViewController is not null)
{
vc = vc.PresentedViewController;
}

vc.SetNeedsStatusBarAppearanceUpdate();

return true;
}
}

0 comments on commit 9cabfd1

Please sign in to comment.