最近、Swiftでのみ記述されたコードをUE4のプロジェクトに統合するという問題が発生しました。同時に、「ObjectiveCのすべてをすばやく書き直そう」というオプションは考慮されていませんでした。既製の解決策はどこにも見つかりませんでした。よくあることですが、幅と深さの両方を掘り下げる必要がありました。問題は正常に解決され、他の誰かを助けるために私はチュートリアルを書くことにしました。
通常、iOS / macOSプラットフォームに固有のコードを統合する必要がある場合、ライブラリアセンブリはフレームワークとして使用されます。フレームワークは静的である必要があります。コード自体はObjectiveCで記述されています。さらに、依存関係はMyProject.Build.cs
、たとえば次のように、プロジェクトビルドスクリプトで記述されています。
if (Target.Platform == UnrealTargetPlatform.IOS)
{
string ExtraPath = Path.GetFullPath(Path.Combine(ModuleDirectory, "../ThirdParty"));
PublicAdditionalFrameworks.Add(
new Framework(
"MyFramework",
ExtraPath + "/" + "MyFramework.framework.zip"
)
);
}
Swiftの場合も同じように試すことができますが、問題が発生します。一部の言語ライブラリに依存しています。リンクの警告は次のようになります。
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'
その後、オブジェクトファイルで一部のシンボルが見つからなかったという標準エラーが発生します。上記の各ライブラリがどこにあるかを見つけて、Lキーを使用してそのライブラリへのパスを指定することができますが、Framework動的タイプに切り替えることにしました。これ自体がこれらのライブラリをロードします。
, 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"));
}
}
}
そして、ファイルは次のMyProject_IOS_UPL.xml
ようになります。
<?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>
このソリューションは、UE4で通常の動的フレームワークがサポートされるまでは一種の回避策ですが、私は完全に満足しました。