Skip to content

Commit

Permalink
Add iOS/Catalyst support to Microsoft.Maui.PlatformChannels
Browse files Browse the repository at this point in the history
  • Loading branch information
chamons committed Jul 21, 2022
1 parent 28eefec commit 0689b0d
Show file tree
Hide file tree
Showing 6 changed files with 132 additions and 12 deletions.
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFrameworks>net6.0-android</TargetFrameworks>
<TargetFrameworks>net6.0-android;net6.0-ios;net6.0-maccatalyst</TargetFrameworks>
<UseMaui>true</UseMaui>
<SingleProject>true</SingleProject>
<ImplicitUsings>enable</ImplicitUsings>
Expand All @@ -16,6 +16,12 @@
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Microsoft.PlatformChannels\Microsoft.PlatformChannels.csproj" />
</ItemGroup>
<ItemGroup Condition="$(TargetFramework.Contains('-android'))">
<ProjectReference Include="..\Microsoft.PlatformChannels.Binding\Microsoft.PlatformChannels.Binding.csproj" />
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'net6.0-ios' OR '$(TargetFramework)' == 'net6.0-maccatalyst'">
<ProjectReference Include="..\Platforms\Apple\Microsoft.PlatformChannels.Binding.Apple\Microsoft.PlatformChannels.Binding.Apple.csproj" />
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
global using PlatformView = global::UIKit.UIView;
global using PlatformObject = global::Foundation.NSObject;
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
using Microsoft.Maui.Handlers;
using Microsoft.PlatformChannels;
using Foundation;
using UIKit;

using iOSViewChannel = Microsoft.PlatformChannels.Platform.ViewChannel;

namespace Microsoft.Maui.PlatformChannels;

public partial class PlatformChannelViewHandler : ViewHandler<IPlatformChannelView, UIKit.UIView>
{
iOSViewChannel platformViewChannel;
PlatformManagedHandler managedHandler;
UIView viewGroup;

protected string ChannelTypeId { get; private set; }
protected string ChannelInstanceId { get; private set; }

IChannelService channelService;

protected override UIKit.UIView CreatePlatformView()
{
if (viewGroup is null) {
viewGroup = new UIView(new CoreGraphics.CGRect(0, 0, 400, 100));
}
EnsureChannelCreated();
return viewGroup;
}

void EnsureChannelCreated()
{
if (string.IsNullOrEmpty(VirtualView?.ChannelTypeId))
return;

var instanceId = VirtualView?.ChannelInstanceId ?? ChannelService.DEFAULT_INSTANCE_ID;

// Is the new id the same as the old?
if (VirtualView?.ChannelTypeId == ChannelTypeId)
{
// Is the instance null on both (so both default and the same)
// or is the new instance Id not the same as the old
if (instanceId == ChannelInstanceId)
return; // No change to actual channel, return
}

channelService ??= MauiContext.Services.GetRequiredService<IChannelService>();

if (platformViewChannel is not null)
{
foreach (var subview in viewGroup.Subviews) {
subview.RemoveFromSuperview ();
}

if (viewGroup.Superview is not null)
viewGroup.RemoveFromSuperview ();

channelService.DisposeChannel(ChannelTypeId, ChannelInstanceId);
platformViewChannel = null;
}

ChannelTypeId = VirtualView.ChannelTypeId;
ChannelInstanceId = instanceId;

var channel = Microsoft.PlatformChannels.Platform.ChannelService.GetOrCreate(ChannelTypeId, ChannelInstanceId);

if (channel == null) {
throw new InvalidOperationException($"No registered ViewChannel found for: '{ChannelTypeId}', instance: '{ChannelInstanceId}'");
}

if (channel is not iOSViewChannel viewChannel)
throw new InvalidCastException($"Registered channel '{ChannelTypeId}' is not a 'ViewChannel' type for instance: '{ChannelInstanceId}");

platformViewChannel = viewChannel;

managedHandler = new PlatformManagedHandler((id, parameters) =>
{
return OnReceivedFromPlatform?.Invoke(id, parameters);
});

platformViewChannel.SetManagedHandler(managedHandler);

var platformView = platformViewChannel.GetPlatformView();
viewGroup.AddSubview (platformView);
}

public static void MapChannelTypeId(IPlatformViewHandler handler, IPlatformChannelView view)
{
if (handler is PlatformChannelViewHandler h)
h.EnsureChannelCreated();
}

public static void MapChannelInstanceId(IPlatformViewHandler handler, IPlatformChannelView view)
{
if (handler is PlatformChannelViewHandler h)
h.EnsureChannelCreated();
}

internal object SendToPlatformImpl(string messageId, object[] args)
{
var platformObjs = args.ToPlatformObjects();

var platformResp = platformViewChannel?.OnChannelMessage(messageId, platformObjs);

var result = platformResp.ToDotNetObject();

return result;
}

class PlatformManagedHandler : NSObject, Microsoft.PlatformChannels.Platform.IChannelMessageHandler
{
public PlatformManagedHandler(Func<string, object[], object> callback)
{
Callback = callback;
}

protected readonly Func<string, object[], object> Callback;

public PlatformObject OnChannelMessage(string id, PlatformObject[] parameters)
=> Callback?.Invoke(id, parameters.ToDotNetObjects()).ToPlatformObject();
}
}
11 changes: 0 additions & 11 deletions Microsoft.Maui.PlatformChannels/Platforms/iOS/ViewChannel.ios.cs

This file was deleted.

0 comments on commit 0689b0d

Please sign in to comment.