ios 8:捆绑路径更改

ios 8:捆绑路径更改,ios,objective-c,Ios,Objective C,我有一个iOS应用程序,它在数据库和生成的html文档中存储文件的绝对路径。我最近刚刚将我的iPhone升级到iOS 8,现在每当我运行这个应用程序时,它似乎每次重新编译都安装在不同的目录中。例如,在第一次生成/运行时,[[NSBundle mainBundle]bundlePath]在下一次生成/运行时返回不同的内容。发生了什么事?这是苹果的新功能吗 更新:已创建错误报告 代码示例: 如果我在多个构建/运行中运行以下行,那么每次都会得到不同的结果 #define kOLD_PATH @"old

我有一个iOS应用程序,它在数据库和生成的html文档中存储文件的绝对路径。我最近刚刚将我的iPhone升级到iOS 8,现在每当我运行这个应用程序时,它似乎每次重新编译都安装在不同的目录中。例如,在第一次生成/运行时,[[NSBundle mainBundle]bundlePath]在下一次生成/运行时返回不同的内容。发生了什么事?这是苹果的新功能吗

更新:已创建错误报告

代码示例:

如果我在多个构建/运行中运行以下行,那么每次都会得到不同的结果

#define kOLD_PATH @"oldPath"
NSString* newPath = [NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES) lastObject];
NSString* oldPath = [[NSUserDefaults standardUserDefaults] objectForKey:kOLD_PATH];

NSLog(@"New Path: %@", newPath);
NSLog(@"Old Path: %@", oldPath);
NSLog(@"Result: %@", [oldPath isEqualToString:newPath] ? @"Same" : @"Changed");

[[NSUserDefaults standardUserDefaults] setObject:newPath forKey:kOLD_PATH];
[[NSUserDefaults standardUserDefaults] synchronize];
在多次运行时,输出结果如下所示

New Path: /var/mobile/Containers/Data/Application/4FFCE2CB-580D-409A-90CB-EF2B8A1FB653/Library
Old Path: /var/mobile/Containers/Data/Application/B038B2DA-F85D-4E18-A5F1-8635834EC454/Library
Result: Changed

完全披露:在我的应用程序中,用户导入一个包含资源的网页(ePub)。资源与网页一起存储。该网页还访问作为应用程序包一部分的资源。为了在加载网页时实现这一点,将基本url设置为网页所在的目录,并通过绝对文件路径访问捆绑资源。既然文件路径在每次更新时都会发生变化,那么这就被破坏了。我尝试创建指向捆绑资源的符号链接,但后续更新也失败

在iOS 8中,应用程序容器的文件系统布局已更改。应用程序及其内容不再存储在一个根目录中

从iOS 8发行说明中:

磁盘上应用程序容器的文件系统布局已更改。相当地 与依赖硬编码目录结构相比,使用 功能或 方法 班级。再见

这不是一个bug。确保您使用了推荐的API(来自上面的引用),您不会有问题

因此,如果您试图访问添加到项目中的捆绑资源,您将使用:

[[NSBundle mainBundle] pathForResource:@"resourceName" ofType:@"extension"];
[[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject] stringByAppendingPathComponent:@"resourceName.extension"];
但是,如果要使用放入documents目录中的内容,可以使用:

[[NSBundle mainBundle] pathForResource:@"resourceName" ofType:@"extension"];
[[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject] stringByAppendingPathComponent:@"resourceName.extension"];

我认为每个构建和运行的不同路径是iOS模拟器中发生事情的预期方式。这不是一个问题

/var/mobile/Containers/Data/Application/4FFCE2CB-580D-409A-90CB-EF2B8A1FB653/库 /var/mobile/Containers/Data/Application/B038B2DA-F85D-4E18-A5F1-8635834EC454/库

我发现即使你使用推荐的方法

- (NSURL *)applicationDocumentsDirectory
{
    return [[[NSFileManager defaultManager] URLsForDirectory:NSLibraryDirectory inDomains:NSUserDomainMask] lastObject];
}

结果是一样的。每个构建和运行的路径不同。

不知道您是否解决了问题,但此链接可能是答案

使用书签定位文件

本页本节前面的几行文字如下:

“重要提示:虽然在应用程序运行时可以安全使用,但在应用程序启动之间存储和重用文件引用URL并不安全,因为如果系统重新启动,文件的ID可能会更改。如果要在应用程序启动之间持久存储文件位置,请按照“使用书签定位文件”中的说明创建书签。“

再见。

突破性变化是

从iOS 8开始,文档和库目录不再显示 应用程序包的较长同级

不要存储文档的完整路径/URL。请存储文件名,并始终使用建议的方法生成完整路径/URL

获取文档目录URL

// Returns the URL to the application's Documents directory.
- (NSURL *)applicationDocumentsDirectory
{
    return [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
}

然后从url中获取路径,并附加文件名以生成完整路径。

在我的应用程序中,我生成的html页面中包含硬编码的文件路径。这些路径现在不断变化。我不确定我应该如何处理此问题。不是真的。我之所以在生成的html中包含绝对路径,是因为我正在使用的脚本g不在基本URL中。html依赖于用户生成的内容(css、图像等)将脚本复制到每个html的基本路径似乎很糟糕。因此html中的脚本绝对引用了该文件。但是,现在该路径每次更新都会更改。我在问题中添加了完整的披露部分,以便您可以真正看到我遇到的确切问题。我可以在mac中访问iPhone模拟器路径,在那里我无法看到iOS 8。如何获取iOS 8路径?@liamnichols我正在看到NSSearchPathForDirectoriesIndomain(NSDocumentDirectory在不同的运行中更改。如果我在一次运行中将文件保存在NSDocumentDirectory中,并在下一次运行中尝试读取该文件,则找不到该文件。这是预期的吗?确实有效。您可以使用指南为该文件创建书签,然后使用反编码Base64将作为NSData的书签更改为NSString,并可以存储该书签字符串来存储文件的位置。当您要读取文件时,您可以将NSString解码到NSData书签,然后解码到文件当前位置的URL。我也经历过同样的行为,但在设备上,而不仅仅是在模拟器上。过去,应用程序的绝对路径只有在升级时才会更改(实际上是安装新版本、迁移数据、删除原始版本)。每次运行应用程序时,我都会看到完整路径发生更改。即使这样,每次运行时,我都会返回不同的路径:\