File: Platform\iOS\ContainerViewController.cs
Web Access
Project: src\src\Core\src\Core.csproj (Microsoft.Maui)
using System;
using System.Diagnostics.CodeAnalysis;
using Microsoft.Maui.HotReload;
using ObjCRuntime;
using UIKit;
 
namespace Microsoft.Maui.Platform
{
	public class ContainerViewController : UIViewController, IReloadHandler
	{
		WeakReference<IElement>? _view;
		[UnconditionalSuppressMessage("Memory", "MEM0002", Justification = "Proven safe in test: NavigationPageTests.DoesNotLeak")]
		UIView? currentPlatformView;
 
		// The handler needs this view before LoadView is called on the controller
		// So this is used to create the first view that the handler will use
		// without forcing the VC to call LoadView
		[UnconditionalSuppressMessage("Memory", "MEM0002", Justification = "Proven safe in test: NavigationPageTests.DoesNotLeak")]
		UIView? _pendingLoadedView;
 
		public IElement? CurrentView
		{
			get => _view?.GetTargetOrDefault();
			set => SetView(value);
		}
 
		public UIView? CurrentPlatformView
			=> _pendingLoadedView ?? currentPlatformView;
 
		[UnconditionalSuppressMessage("Memory", "MEM0002", Justification = "IMauiContext is a non-NSObject in MAUI.")]
		public IMauiContext? Context { get; set; }
 
		void SetView(IElement? view, bool forceRefresh = false)
		{
			if (CurrentView is IElement existingView && view == existingView && !forceRefresh)
				return;
 
			_view = view is null ? null : new(view);
 
			if (view is ITitledElement page)
				Title = page.Title;
 
			if (view is IHotReloadableView ihr)
			{
				ihr.ReloadHandler = this;
				MauiHotReloadHelper.AddActiveView(ihr);
			}
 
			currentPlatformView?.RemoveFromSuperview();
			currentPlatformView = null;
 
			if (IsViewLoaded && view is not null)
				LoadPlatformView(view);
		}
 
		internal UIView LoadFirstView(IElement view)
		{
			_pendingLoadedView = CreatePlatformView(view);
			return _pendingLoadedView;
		}
 
		public override void LoadView()
		{
			base.LoadView();
			if (CurrentView is IElement view && Context != null)
				LoadPlatformView(view);
		}
 
		void LoadPlatformView(IElement view)
		{
			currentPlatformView = _pendingLoadedView ?? CreatePlatformView(view);
			_pendingLoadedView = null;
 
			View!.AddSubview(currentPlatformView);
 
			if (view is IView v && v.Background == null)
				View.BackgroundColor = ColorExtensions.BackgroundColor;
		}
 
		protected virtual UIView CreatePlatformView(IElement view)
		{
			_ = Context ?? throw new ArgumentNullException(nameof(Context));
			_ = _view ?? throw new ArgumentNullException(nameof(view));
 
			return view.ToPlatform(Context);
		}
 
		public override void ViewDidLayoutSubviews()
		{
			base.ViewDidLayoutSubviews();
			if (currentPlatformView == null)
				return;
			currentPlatformView.Frame = View!.Bounds;
		}
 
		public void Reload() => SetView(CurrentView, true);
	}
}