1

当我将我的 iOS 设备设置为例如越南语时,以下代码有时会失败:

var
  lFilePath: String
...
lFilePath := TPath.GetTempPath + '/MyDBfile.db';
lFileStream := TFileStream.Create(lFilePath, fmOpenReadWrite or fmShareExclusive or fmCreate);

TFileStream.Create 调用引发断言:“EFCreateError: Cannot create file "/private/var/mobile/Containers/Data/Application/{containerID}/tmp/MyDBfile.db" No such file or directory"。只有当设备设置为某些语言(包括越南语)时,才不会使用西欧语言提出断言。

我将创建代码跟踪到FileCreate函数的这一行System.SysUtils

FileHandle := Integer(__open(M.AsAnsi(FileName, CP_UTF8).ToPointer,
  O_RDWR or O_CREAT or O_TRUNC or Exclusive[(Mode and $0004) shr 2], Rights));

当提出断言时,FileHandle 为 -1。

有什么问题?

PS:在我试图找出发生了什么时,我添加了一个Fileexists电话:

lFilePath := TPath.GetTempPath + '/MyDBfile.db';
if Fileexists(lFilePath) then
  System.Sysutils.DeleteFile(lFilePath);
lFileStream := TFileStream.Create(lFilePath, fmOpenReadWrite or fmShareExclusive or fmCreate);

现在,在代码失败的情况下,我有以下奇怪的发现:在XCode中,它可以显示App的Container,它显示tmp/MyDBfile.dbContainer中的文件,即文件确实存在(该文件仅由引用的代码,因此它是在代码成功的时间之一创建的)。但是,同时Fileexists返回false。

该文件是一个 SQLite 文件,稍后sqlite3_open_v2sqlite3_close. SQLite 是否可以将文件置于 Fileexists 返回 false 的状态?(重启应用后状态依然存在)

4

1 回答 1

1

问题是当前的实现TPath.GetTempPath。它使用一般的 Posix 方法ExpandFileName('~/tmp/')。但是,Apple 推荐的方法是使用NSTemporaryDirectory.

两种方法都返回tmp目录的路径,但NSTemporaryDirectory如果文件夹不存在,也会创建文件夹——这似乎是不同的。奇怪的是,Delphi 实现仅在某些 iOS 设备语言(包括越南语)下失败。我没有进一步调查,但现在的解决方案是简单地TPath.GetTempPath用这个 Delphi 代码替换:

NSStrToStr(TNSString.Wrap(NSTemporaryDirectory))
于 2016-07-04T09:38:24.527 回答