-->

Document Or cache Path Changes on every launch in

2019-01-18 05:00发布

问题:

As i am downloading a video in my app and keeping it in local cache/Document path and showing when necessary. It is working in iOS 7 but the avplayer not showing video in iOS 8 and above. As i have read that the document/cache path is changed on every launch in iOS 8. The issue is, I have to download video once and show it multiple times in my app. So how can i reach the same path again and again to show video in app.

Here is my code:

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

In The log I am getting different path on each launch. Any Help would be appreciated. Thanks

回答1:

I got the answer. As the absolute path is changing on every launch, we can save the data on relative path and retrieve it on appending absolute path and relative path.

This is how we can save the data on the relative path:

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

But when you read the file you have to use absolute path + relative path:

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

For Database also store data on the relative path only. But while reading take the absolute path and append the relative path coming from database and read.
Its Working here.



回答2:

The path to the application container or sandbox changing should be an expected condition. You should not store the absolute filesystem path to a sandbox directory; instead store the path relative to that directory, and append that to the result of NSSearchPathForDirectoriesInDomains each time.



回答3:

It is recommended to use bookmarks to reference file system resources.

If you want to save the location of a file persistently, use the bookmark capabilities of NSURL. A bookmark is an opaque data structure, enclosed in an NSData object, that describes the location of a file. Whereas path- and file reference URLs are potentially fragile between launches of your app, a bookmark can usually be used to re-create a URL to a file even in cases where the file was moved or renamed.

A bookmark provides a persistent reference to a file-system resource. When you resolve a bookmark, you obtain a URL to the resource’s current location. A bookmark’s association with a file-system resource (typically a file or folder) usually continues to work if the user moves or renames the resource, or if the user relaunches your app or restarts the system.

For a sample code, checkout the File System Programming Guide -> Locating Files Using Bookmarks


If you want use URL directly for backward compatibility, I have a fix code:

@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


标签: ios ios8 ios8.1