源码版与安装版 IOS 数据路径差异

使用安装版引擎打包 IOS 时,开启 FileSharing 能够在通过工具访问程序的 Document 目录,里面类似 Android 的 UE4Game 目录结构。
但是当使用源码版引擎打包时,开启 FileSharing 的包,UE 的数据目录并不在 Document 目录下,因为项目配置没有任何更改,怀疑是引擎中有些地方对源码版或安装版做了检测。
搜索代码发现,引擎中通过 FILESHARING_ENABLED 宏进行检测,当开启时,数据目录位于 Library 目录下,没有开启时则位于 Document 目录下。

Core/Private/IOS/IOSPlatformMisc.cpp
1
2
3
4
5
6
7
8
9
10
void FIOSPlatformMisc::PlatformInit()
{
// ...
#if FILESHARING_ENABLED
FString DownloadPath = FString([NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES) objectAtIndex:0]) + TEXT("/");
#else
FString DownloadPath = FString([NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0]) + TEXT("/");
#endif
// ...
}

这个宏由 UBT 生成,通过读取 DefaultEngine.ini[/Script/IOSRuntimeSettings.IOSRuntimeSettings]下的 bSupportsITunesFileSharing 来确定宏的值。

Source/Programs/UnrealBuildTool/Platform/IOS/UEBuildIOS.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
/// <summary>
/// Stores project-specific IOS settings. Instances of this object are cached by IOSPlatform.
/// </summary>
public class IOSProjectSettings
{
// ...
/// <summary>
/// true if iTunes file sharing support is enabled
/// </summary>
[ConfigFile(ConfigHierarchyType.Engine, "/Script/IOSRuntimeSettings.IOSRuntimeSettings", "bSupportsITunesFileSharing")]
public readonly bool bFileSharingEnabled = false;
// ...
}

添加宏的代码如下:

Source/Programs/UnrealBuildTool/Platform/IOS/UEBuildIOS.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/// <summary>
/// Setup the target environment for building
/// </summary>
/// <param name="Target">Settings for the target being compiled</param>
/// <param name="CompileEnvironment">The compile environment for this target</param>
/// <param name="LinkEnvironment">The link environment for this target</param>
public override void SetUpEnvironment(ReadOnlyTargetRules Target, CppCompileEnvironment CompileEnvironment, LinkEnvironment LinkEnvironment)
{
// ...
if (ProjectSettings.bFileSharingEnabled)
{
CompileEnvironment.Definitions.Add("FILESHARING_ENABLED=1");
}
else
{
CompileEnvironment.Definitions.Add("FILESHARING_ENABLED=0");
}
// ...
}

原因分析:

  1. 因为编译安装版引擎时,没有项目,引擎中 BaseEngine.inibSupportsITunesFileSharing=False,所以通过 BuildGraph 编译安装版引擎时,bFileSharingEnabled默认值是 false,通过安装版引擎打包项目引擎也不会编译了,所以 bFileSharingEnabled 的值一直是 false,使用的是 NSDocumentDirectory 目录
  2. 相同的道理,使用源码版引擎打包项目时,因为需要通过打包项目才编译引擎,如果项目中指定了 bSupportsITunesFileSharing=True,则编译引擎时bFileSharingEnabled 就为 true,导致 FILESHARING_ENABLED=1,则使用了NSLibraryDirectory 目录。

需要注意的是:bSupportsITunesFileSharing不仅仅只是控制数据存储路径,还控制打包时 plist 的生成:

Programs/UnrealBuildTool/Platform/IOS/UEDeployIOS.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public static bool GenerateIOSPList(FileReference ProjectFile, UnrealTargetConfiguration Config, string ProjectDirectory, bool bIsUE4Game, string GameName, bool bIsClient, string ProjectName, string InEngineDir, string AppDirectory, VersionNumber SdkVersion, UnrealPluginLanguage UPL, string BundleID, bool bBuildAsFramework, out bool bSupportsPortrait, out bool bSupportsLandscape, out bool bSkipIcons)
{
// ITunes file sharing
bool bSupportsITunesFileSharing = false;
Ini.GetBool("/Script/IOSRuntimeSettings.IOSRuntimeSettings", "bSupportsITunesFileSharing", out bSupportsITunesFileSharing);
bool bSupportsFilesApp = false;
Ini.GetBool("/Script/IOSRuntimeSettings.IOSRuntimeSettings", "bSupportsFilesApp", out bSupportsFilesApp);

// ...

Text.AppendLine("\t<key>UIFileSharingEnabled</key>");
Text.AppendLine(string.Format("\t<{0}/>", bSupportsITunesFileSharing ? "true" : "false"));
if (bSupportsFilesApp)
{
Text.AppendLine("\t<key>LSSupportsOpeningDocumentsInPlace</key>");
Text.AppendLine("\t<true/>");
}
// ...
}

所以,为了同时支持数据存储在 Document 下和开启 plist 中的UIFileSharingEnabled,对于 FileSharing 功能的支持需要进行以下操作:

  1. DefaultEngine.ini中的bSupportsITunesFileSharing=False
  2. 修改引擎中生成 FILESHARING_ENABLED 宏的代码,保持为 false 即可