Recentemente, surgiu o problema de integrar o código que foi escrito apenas em Swift em um projeto no UE4. Ao mesmo tempo, a opção "vamos reescrever tudo rapidamente em Objective C" não foi considerada. Não encontrei uma solução pronta em lugar nenhum, tive, como sempre acontece, que cavar tanto em amplitude quanto em profundidade. O problema foi resolvido com sucesso e para ajudar outra pessoa decidi escrever um tutorial.
Normalmente, se você precisa integrar algum código específico à plataforma iOS / macOS, o assembly da biblioteca é usado como um Framework, que deve ser estático. O código em si é escrito no Objetivo C. Além disso, a dependência é escrita no script de construção do projeto MyProject.Build.cs, por exemplo, assim:
if (Target.Platform == UnrealTargetPlatform.IOS)
{
string ExtraPath = Path.GetFullPath(Path.Combine(ModuleDirectory, "../ThirdParty"));
PublicAdditionalFrameworks.Add(
new Framework(
"MyFramework",
ExtraPath + "/" + "MyFramework.framework.zip"
)
);
}
Para o Swift, você pode tentar seguir o mesmo caminho, mas haverá um problema - dependência de algumas bibliotecas de linguagem. O aviso do link será semelhante a este:
ld: warning: Could not find auto-linked library 'swiftFoundation'
ld: warning: Could not find auto-linked library 'swiftDarwin'
ld: warning: Could not find auto-linked library 'swiftCoreFoundation'
ld: warning: Could not find auto-linked library 'swiftCore'
ld: warning: Could not find auto-linked library 'swiftCoreGraphics'
ld: warning: Could not find auto-linked library 'swiftObjectiveC'
ld: warning: Could not find auto-linked library 'swiftDispatch'
ld: warning: Could not find auto-linked library 'swiftSwiftOnoneSupport'
Depois disso, erros padrão seguirão que alguns símbolos não foram encontrados nos arquivos de objeto. Você pode tentar descobrir onde cada biblioteca mencionada acima está localizada e especificar o caminho para ela por meio da tecla L, mas decidi mudar para o tipo dinâmico de Framework, que carregará essas bibliotecas por conta própria.
, iOS :
dyld: Library not loaded: @rpath/MyFramework.framework/MyFramework
Referenced from: /private/var/mobile/Containers/Bundle/Application/.../MyApp.app/MyApp
Reason: image not found
, UE4 Framework, . IOS Toolchain , IOSPlugin.
plist , , :
<iosPListUpdates>
<addElements tag="dict" once="true">
<key>NSCameraUsageDescription</key>
<string>The camera is used for live preview.</string>
</addElements>
</iosPListUpdates>
copyDir. , , :
<init>
<log text="Copy MyFramwork..."/>
<copyDir src="/.../MyFramework.framework" dst="$S(BuildDir)/Frameworks/MyFramework.framework" />
</init>
, init. .
MyProject.Build.cs :
using UnrealBuildTool;
using System.IO;
public class MyProject : ModuleRules
{
public MyProject(ReadOnlyTargetRules Target) : base(Target)
{
PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs;
PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore" });
if (Target.Platform == UnrealTargetPlatform.IOS)
{
string ExtraPath = Path.GetFullPath(Path.Combine(ModuleDirectory, "../ThirdParty"));
PublicAdditionalFrameworks.Add(
new Framework(
"MyFramework",
ExtraPath + "/" + "MyFramework.framework.zip"
)
);
string PluginPath = Utils.MakePathRelativeTo(ModuleDirectory, Target.RelativeEnginePath);
AdditionalPropertiesForReceipt.Add("IOSPlugin", Path.Combine(PluginPath, "MyProject_IOS_UPL.xml"));
}
}
}
E o arquivo é MyProject_IOS_UPL.xmlassim:
<?xml version="1.0" encoding="utf-8"?>
<root>
<init>
<log text="Copy MyFramework..."/>
<copyDir src="/.../MyFramework.framework" dst="$S(BuildDir)/Frameworks/MyFramework.framework" />
</init>
</root>
Esta solução é uma espécie de contorno até que haja suporte para Framework dinâmico normal no UE4, mas eu estava completamente satisfeito com ela.