'How to easily share code between iOS and Mac Catalyst in .net 6?

I'm in the process of upgrading a Xamarin Native solution to run on .net 6 using SDK style multi-targetted projects.

As I understand it, there are two ways of writing platform-dependent code: a) Code inside the appropriate platform directory (e.g. "iOS" or "MacCatalyst") is always compiled conditionally for that platform. b) Code can be explicitly conditionally compiled via e.g., #if IOS.

Neither of these seems ideal when there is a large body of code that is shared between two platforms. In (a) the code is duplicated and in (b) the code is strewn with #ifs.

Is there a better way to share code between these two platforms?



Solution 1:[1]

I'm considering creating a "Shared" folder under Platforms/iOS and symlinking that folder to Platforms/MacCatalyst/Shared.

Still holding out for other answers, as well as comments on this one.

EDIT: I tried this on Visual Studio For Mac 2022. The symlinked folder at Platforms/MacCatalyst/Shared appears as a single file with a reddish title in Solution Explorer, i.e., its subtree isn't visible. However, the project complies fine for both iOS and Mac Catalyst. Since the shared code is accessible from its original location at Platforms/iOS/Shared, this looks like valid albeit somewhat unsupported strategy.

Solution 2:[2]

MSBuild Conditions can be used to control build actions under different circumstances.

Given the default value true of <EnableDefaultCompileItems>, the easiest approach is to REMOVE a folder from targets that shouldn't have it.

The goal is to have (most) iOS code be included on both iOS and MacCatalyst; therefore exclude it from all other target frameworks.

Steps:

  • Create a folder under the project root. E.g. iosShared.
  • Place in that, the files (and subfolders) to include in both iOS and MacCatalyst builds.
  • By default, those files would be included for all targets. Stop that by adding to YourProject.csproj:
    <ItemGroup Condition="'$(TargetFramework)' != 'net6.0-ios' And
                          '$(TargetFramework)' != 'net6.0-maccatalyst'">
        <Compile Remove="iosShared\**\*" />
    </ItemGroup>

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2