【问题标题】:ios 8: Bundle path changesios 8:捆绑路径更改
【发布时间】:2014-11-11 02:59:16
【问题描述】:

我有一个 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 objective-c


    【解决方案1】:

    在 iOS 8 中,应用容器的文件系统布局发生了变化。应用程序及其内容不再存储在一个根目录中。

    来自 iOS 8 发行说明:

    应用容器的文件系统布局在磁盘上发生了变化。相当 与依赖硬编码的目录结构相比,使用 NSSearchPathForDirectoriesInDomains 函数或 URLForDirectory:inDomain:appropriateForURL:create:error:方法的 NSFileManager 班级。请参阅File System Programming Guide 中的Accessing Files and Directories

    这不是错误。确保您使用推荐的 API(来自上述引用),您不会遇到问题。

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

    [[NSBundle mainBundle] pathForResource:@"resourceName" ofType:@"extension"];
    

    但如果你想使用放在文档目录中的东西,你会使用:

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

    【讨论】:

    • 在我的应用程序中,我生成了包含硬编码文件路径的 html 页面。这些路径现在在不断变化。我不确定我应该如何处理。
    • 并非如此。我在生成的 html 中有绝对路径的原因是因为我使用的脚本不在基本 URL 中。 html 依赖于用户生成的内容(css、图像等),并且将脚本复制到每个 html 的基本路径中似乎很糟糕。因此 html 中的脚本绝对引用了该文件。但是现在这条路径每次更新都会改变。
    • 我在问题中添加了一个完整的披露部分,这样您就可以真正看到我遇到的确切问题。
    • 我可以在我的 Mac 中进入 iPhone 模拟器路径,但我无法看到 iOS 8。如何获取 iOS 8 路径?。
    • @liamnichols 我看到 NSSearchPathForDirectoriesInDomains(NSDocumentDirectory 从运行更改为运行。如果我在一次运行中将文件保存在 NSDocumentDirectory 中并尝试在下一次运行时读取它,则找不到它。是那是预期的吗?
    【解决方案2】:

    Refer Technical Note 2406 by Apple

    重大变化是

    从 iOS 8 开始,Documents 和 Library 目录没有 应用程序包的较长同级。

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

    获取 DocumentsDirectory URL

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

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

    【讨论】:

    • 即使这样每次我运行时都会返回不同的路径:\
    【解决方案3】:

    不知道你是否解决了你的问题,但这个链接可能是答案。

    https://developer.apple.com/library/prerelease/ios/documentation/FileManagement/Conceptual/FileSystemProgrammingGuide/AccessingFilesandDirectories/AccessingFilesandDirectories.html#//apple_ref/doc/uid/TP40010672-CH3-SW10

    使用书签定位文件

    页面中此部分之前的几行是此文本:

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

    再见。

    【讨论】:

    • 它确实有效。您可以使用指南为文件创建书签,然后使用 de encode Base64 将书签(即 NSData)更改为 NSString,然后您可以存储该字符串以存储文件的位置。当您想读取文件时,您将 NSString 解码为 NSData 书签,然后解码为文件当前位置的 URL。
    【解决方案4】:

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

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

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

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

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

    【讨论】:

    • 我遇到了同样的行为,但在设备上而不是在模拟器上。曾经是应用程序的绝对路径只有在升级时才会改变(实际上是安装新版本,迁移数据,删除原始版本)。我看到每次应用运行时完整路径都会发生变化。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-07-09
    • 2019-11-25
    • 2011-03-30
    • 2011-06-24
    • 1970-01-01
    • 2011-04-23
    • 2015-01-04
    相关资源
    最近更新 更多