14

当我在我的应用程序中下载视频并将其保存在本地缓存/文档路径中并在必要时显示时。它在 iOS 7 中工作,但 avplayer 在 iOS 8 及更高版本中不显示视频。正如我所读到的,在 iOS 8 中每次启动时都会更改文档/缓存路径。问题是,我必须下载一次视频并在我的应用程序中多次显示。那么我怎样才能一次又一次地到达相同的路径以在应用程序中显示视频。

Here is my code:

NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
// NSLog(@"Document folder: %@", paths);
NSString *documentsDirectory = [paths objectAtIndex:0];
   NSLog(@"Document folder: %@", documentsDirectory);

在日志中,每次启动我都会得到不同的路径。任何帮助,将不胜感激。谢谢

4

3 回答 3

16

我得到了答案。由于每次启动时绝对路径都在变化,我们可以将数据保存在相对路径中,并在附加绝对路径和相对路径时检索它。

这就是我们如何将数据保存在相对路径上:

NSString *documentsDirectory = @"MyFolder";
documentsDirectory = [documentsDirectory stringByAppendingPathComponent:filename];
NSString *relativePath = documentsDirectory;

但是当您读取文件时,您必须使用绝对路径 + 相对路径:

  NSFileManager *fileManager = [NSFileManager defaultManager];
  NSString *fullCachePath = ((NSURL*)[[fileManager URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject] ).path;
  NSString *fullPath = [fullCachePath stringByAppendingPathComponent:relativePath];  

对于数据库,也仅将数据存储在相对路径上。但是在读取时采用绝对路径并附加来自数据库的相对路径并读取。
它在这里工作。

于 2014-12-12T11:57:13.760 回答
8

应用程序容器或沙箱更改的路径应该是预期的条件。您不应该将绝对文件系统路径存储到沙盒目录;而是存储对于该目录的路径,并将其附加到NSSearchPathForDirectoriesInDomains每次的结果中。

于 2014-11-18T06:58:56.103 回答
0

推荐使用书签来引用文件系统资源。

如果要永久保存文件的位置,请使用 NSURL 的书签功能。书签是一种不透明的数据结构,包含在 NSData 对象中,用于描述文件的位置。虽然路径和文件引用 URL 在您的应用程序启动之间可能很脆弱,但书签通常可用于重新创建文件的 URL,即使在文件被移动或重命名的情况下也是如此。

书签提供对文件系统资源的持久引用。解析书签时,您将获得资源当前位置的 URL。如果用户移动或重命名资源,或者如果用户重新启动您的应用程序或重新启动系统,书签与文件系统资源(通常是文件或文件夹)的关联通常会继续工作。

有关示例代码,请查看文件系统编程指南 -> 使用书签定位文件


如果您想直接使用 URL 来实现向后兼容性,我有一个修复代码:

@interface NSURL (App)

/**
 This method try to rebuild a file url relative to application’s home directory.
 
 If the reciver is not a file url or not in the home directory. The original URL returns.
 
 @code
 
 NSString *homePath = NSHomeDirectory();
 // Assume "/Something/Application/B383551F-41C1-4E3D-8EA9-8D76E4AFA919"
 
 NSURL *test;
 test = [NSURL fileURLWithPath:homePath];
 [test URLByResolvingApplicationDirectoryChange];
 // file://Something/Application/B383551F-41C1-4E3D-8EA9-8D76E4AFA919
 
 test = [NSURL URLWithString:@"file:///Foo/bar"];
 [test URLByResolvingApplicationDirectoryChange];
 // file:///Foo/bar
 
 test = [NSURL URLWithString:@"file://Something/Application/12345678-1234-1234-1234-123456789ABC/path.tmp"];
 // file://Something/Application/B383551F-41C1-4E3D-8EA9-8D76E4AFA919/path.tmp
 
 @endcode
 */
- (nonnull NSURL *)URLByResolvingApplicationDirectoryChange;

@end


@implementation NSURL (App)

- (nonnull NSURL *)URLByResolvingApplicationDirectoryChange {
    if (!self.isFileURL) return self;

    NSString *pathHome = NSHomeDirectory();
    NSString *pathThis = self.path;
    if ([pathThis hasPrefix:pathHome]) {
        return self;
    }

    NSArray<NSString *> *cpHome = pathHome.pathComponents;
    NSMutableArray<NSString *> *cpThis = pathThis.pathComponents.mutableCopy;
    if (cpThis.count < cpHome.count) {
        return self;
    }

    NSInteger i = 0;
    for (i = 0; i < cpHome.count - 2; i++) {
        NSString *hp = cpHome[i];
        NSString *tp = cpThis[i];
        if (![hp isEqualToString:tp]) {
            return self;
        }
    }
    i++;
    NSString *hp = cpHome[i];
    NSString *tp = cpThis[i];
    if (hp.length != tp.length) {
        return self;
    }
    [cpThis replaceObjectAtIndex:i withObject:hp];
    NSString *resolvedPath = [NSString pathWithComponents:cpThis];
    return [NSURL.alloc initFileURLWithPath:resolvedPath];
}

@end
于 2018-11-13T05:25:17.133 回答