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