xamarin 如何在.net 6中轻松地在iOS和Mac Catalyst之间共享代码?

kd3sttzy  于 11个月前  发布在  .NET
关注(0)|答案(3)|浏览(138)

我正在使用SDK风格的多目标项目升级Xamarin Native解决方案以在.net 6上运行。
据我所知,有两种编写平台相关代码的方法:a)在适当的平台目录(例如“iOS”或“MacCatalyst”)中的代码总是针对该平台有条件地编译。B)代码可以通过例如#if IOS显式地有条件地编译。
当两个平台之间共享大量代码时,这两种方法都不理想。在(a)中,代码是重复的,在(b)中,代码中散布着#if s。
有没有更好的方法在这两个平台之间共享代码?

iswrvxsc

iswrvxsc1#

MSBuild Conditions可用于控制不同环境下的构建操作。
给定<EnableDefaultCompileItems>的默认值true,最简单的方法是从不应该有它的目标中删除文件夹。
我们的目标是让(大多数)iOS代码同时包含在iOS和MacCatalyst上;因此将其从所有其他目标框架中排除。
步骤:

  • 在项目根目录下创建一个文件夹。例如iosShared
  • 在其中放置要包含在iOS和MacCatalyst构建中的文件(和文件夹)。
  • 默认情况下,这些文件将包含在所有目标中。通过添加到YourProject.csproj来停止此操作:
<ItemGroup Condition="'$(TargetFramework)' != 'net6.0-ios' And
                          '$(TargetFramework)' != 'net6.0-maccatalyst'">
        <Compile Remove="iosShared\**\*" />
    </ItemGroup>

字符串

ckocjqey

ckocjqey2#

我正在考虑在Platforms/iOS下创建一个“共享”文件夹,并将该文件夹符号链接到Platforms/MacCatalyst/Shared
仍然坚持其他答案,以及对这一个的评论。
编辑:我在Visual Studio For Mac 2022上尝试了这个方法。位于Platforms/MacCatalyst/Shared的符号链接文件夹在解决方案资源管理器中显示为一个带有红色标题的单个文件,也就是说,它的子树不可见。然而,该项目在iOS和Mac Catalyst上都符合要求。由于共享代码可以从位于Platforms/iOS/Shared的原始位置访问,因此这看起来是有效的,尽管有点不受支持。

fae0ux8s

fae0ux8s3#

加入讨论很晚了。这是我提出的解决方案。下面的片段智能地复制了那些在iOS中更改的.cs文件,并确保删除MacCatalyst下的任何.cs文件,这些文件在iOS下不再有等效的兄弟文件。
请注意,如果您要在CI管道中使用它,则必须在.csproj上启动构建之前显式地单独调用目标'CloneIOSSourceCodeToMacCatalyst_Impl',如下所示:

<!-- its vital to call this target explicitly before compilation kicks in -->
<Message Importance="High" Text="** [Builder] Copying iOS *.cs -> MacCatalyst"/>
<MSBuild Projects="path/to/your/project.csproj" Targets="CloneIOSSourceCodeToMacCatalyst_Impl"/>
        
<!-- COMPILE  -->
<MSBuild Projects="path/to/your/project.csproj" Targets="Build"/>

字符串
和snippet本身:

<!-- this is meant to be an automation automatically invoked by the IDE itself to make our lives a bit easier -->
    <Target Condition=" $([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'maccatalyst' "
            Name="CloneIOSSourceCodeToMacCatalyst"
            BeforeTargets="CoreCompile">
        <CallTarget Targets="CloneIOSSourceCodeToMacCatalyst_Impl"/>
    </Target>

    <!-- we made this a separate target without conditions so that it will be directly invocable by our build script -->
    <Target Name="CloneIOSSourceCodeToMacCatalyst_Impl">
        <Message Importance="High" Text="**** [CloneIOSSourceCodeToMacCatalyst_Impl] Copying iOS *.cs -> MacCatalyst"/>

        <!-- intelligently copy over only the files that changed from ios -->
        <ItemGroup>
            <iOSFiles Include="Platforms\iOS\**\*.*"/>
        </ItemGroup>

        <Copy SourceFiles="@(iOSFiles)"
              DestinationFolder="Platforms\MacCatalyst\%(RecursiveDir)"
              SkipUnchangedFiles="true"/>
        
        <!-- and now delete all those files under mac-catalyst that no longer have an equivalent sibling file under ios -->
        <ItemGroup>
            <MacCatalystSourceFiles Include="$([System.IO.Directory]::GetFiles('Platforms\MacCatalyst', '*.cs', SearchOption.AllDirectories))" />

            <MacCatalystSourceFiles>
                <RespectiveIosFilePath>$([System.String]::Copy('%(Identity)').Replace('MacCatalyst', 'iOS'))</RespectiveIosFilePath>
            </MacCatalystSourceFiles>

            <RespectiveIosFiles Include="@(MacCatalystSourceFiles->'%(RespectiveIosFilePath)')" />
            <RespectiveIosFilesThatDontExist Include="@(RespectiveIosFiles)" Condition=" !Exists(%(RespectiveIosFiles.Identity)) " />

            <RespectiveIosFilesThatDontExist>
                <RespectiveMacCatalystFilePath>$([System.String]::Copy('%(Identity)').Replace('iOS', 'MacCatalyst'))</RespectiveMacCatalystFilePath>
            </RespectiveIosFilesThatDontExist>

            <MacCatalystStrayFilesToDelete Include="@(RespectiveIosFilesThatDontExist->'%(RespectiveMacCatalystFilePath)')" />
        </ItemGroup>

        <Delete Files="@(MacCatalystStrayFilesToDelete)" />

        <Touch Files="Platforms\MacCatalyst\_DONT_EDIT_ANY_FILES_IN_HERE__ITS_POINTLESS_" AlwaysCreate="true" Condition=" !Exists('Platforms\MacCatalyst\_DONT_EDIT_ANY_FILES_IN_HERE__ITS_POINTLESS_') " />
    </Target>

相关问题