当我的应用程序在iPhone上运行时,我有一个错误,但是当它在模拟器上运行时却没有。我使用主目录路径的长度来提取/ Documents中文件的相对路径。不幸的是,这并不总能在iPhone上正常工作,因为前缀“/ private”正被添加到主路径中。但是,无论有没有前缀,都可以引用相同的文件。以下代码演示了这种不一致性。 “/ private”的目的是什么?iOS何时提供?
- (IBAction)testHomepath:(id)sender {
NSFileManager *fmgr = [NSFileManager defaultManager];
NSString *homePath = [NSString stringWithFormat:@"%@/Documents",NSHomeDirectory()];
NSString *dirPath = [homePath stringByAppendingPathComponent:@"TempDir"];
NSURL *dirURL = [NSURL fileURLWithPath:dirPath];
NSString *filePath = [dirPath stringByAppendingPathComponent:@"test.jpg"];
[fmgr createDirectoryAtPath:dirPath withIntermediateDirectories:NO attributes:nil error:nil];
[fmgr createFileAtPath:filePath contents:nil attributes:nil];
NSArray *keys = [[NSArray alloc] initWithObjects:NSURLNameKey,nil];
NSArray *files = [fmgr contentsOfDirectoryAtURL:dirURL includingPropertiesForKeys:keys options:0 error:nil];
NSURL *f1 = (files.count>0)? [files objectAtIndex:0] : 0;
NSURL *f2 = (files.count>1)? [files objectAtIndex:1] : 0;
bool b0 = [fmgr fileExistsAtPath:filePath];
bool b1 = [fmgr fileExistsAtPath:f1.path];
bool b2 = [fmgr fileExistsAtPath:f2.path];
NSLog(@"File exists=%d at path:%@",b0,filePath);
NSLog(@"File exists=%d at path:%@",b1,f1.path);
NSLog(@"File exists=%d at path:%@",b2,f2.path);
}
在iPhone上运行时,以下内容写入日志。我手动间隔输出以显示第1行和第2行之间的差异。
2013-02-20 16:31:26.615 Test1[4059:907] File exists=1 at path: /var/mobile/Applications/558B5D82-ACEB-457D-8A70-E6E00DB3A484/Documents/TempDir/test.jpg
2013-02-20 16:31:26.622 Test1[4059:907] File exists=1 at path:/private/var/mobile/Applications/558B5D82-ACEB-457D-8A70-E6E00DB3A484/Documents/TempDir/test.jpg
2013-02-20 16:31:26.628 Test1[4059:907] File exists=0 at path:(null)
在模拟器上运行时,以下内容写入日志(无“/ private”):
2013-02-20 16:50:38.730 Test1[7224:c07] File exists=1 at path:/Users/kenm/Library/Application Support/iPhone Simulator/6.1/Applications/C6FDE177-958C-4BF5-8770-A4D3FBD281F1/Documents/TempDir/test.jpg
2013-02-20 16:50:38.732 Test1[7224:c07] File exists=1 at path:/Users/kenm/Library/Application Support/iPhone Simulator/6.1/Applications/C6FDE177-958C-4BF5-8770-A4D3FBD281F1/Documents/TempDir/.DS_Store
2013-02-20 16:50:38.733 Test1[7224:c07] File exists=1 at path:/Users/kenm/Library/Application Support/iPhone Simulator/6.1/Applications/C6FDE177-958C-4BF5-8770-A4D3FBD281F1/Documents/TempDir/test.jpg
答案 0 :(得分:29)
我在调试器中尝试了这一点,发现URLByResolvingSymlinksInPath
“修复了/private/
添加内容。
(lldb) p (NSURL *)[NSURL fileURLWithPath:@"/private/var" isDirectory:YES]
(NSURL *) $1 = 0x1fd9fc20 @"file://localhost/private/var/"
(lldb) po [$1 URLByResolvingSymlinksInPath]
$2 = 0x1fda0190 file://localhost/var/
(lldb) p (NSURL *)[NSURL fileURLWithPath:@"/var" isDirectory:YES]
(NSURL *) $7 = 0x1fd9fee0 @"file://localhost/var/"
(lldb) po [$7 URLByResolvingSymlinksInPath]
$8 = 0x1fda2f50 file://localhost/var/
如您所见,file://localhost/var
是我们真正想要的。
因此,/private/var
似乎是/var
的符号链接。
然而,@ Kevin-Ballard指出这不是真的。我确认他是正确的,/var
是/private/var
(叹气)的符号链接
(lldb) p (NSDictionary *)[[NSFileManager defaultManager] attributesOfItemAtPath:@"/var" error:nil]
(NSDictionary *) $3 = 0x1fda11b0 13 key/value pairs
(lldb) po $3
$3 = 0x1fda11b0 {
...
NSFileType = NSFileTypeSymbolicLink;
}
(lldb) p (NSDictionary *)[[NSFileManager defaultManager] attributesOfItemAtPath:@"/private/var" error:nil]
(NSDictionary *) $5 = 0x1fda4820 14 key/value pairs
(lldb) po $5
$5 = 0x1fda4820 {
...
NSFileType = NSFileTypeDirectory;
}
所以URLByResolvingSymlinksInPath
在这里做了一些有趣的事情,但现在我们知道了。对于这个特殊问题,URLByResolvingSymlinksInPath
仍然听起来像是一个适用于模拟器和设备的好解决方案,并且如果发生变化,将来还能继续工作。
答案 1 :(得分:5)
在 Swift 3中,URL
具有standardizedFileUrl
属性,该属性将移除所有符号链接并解析路径中的相对部分,如./
。
截至撰写时documentation非常无用,但看起来它与NSURL
's standardized
属性相当。
答案 2 :(得分:4)
要真正回答你的问题:
我相信/private
是在发布OS X时添加的前缀(我不认为它在NeXTStep中存在,但它已经几十年)。似乎存在容纳etc
,var
和tmp
(奇怪的是,tftpboot
;我不知道我的PBG4可以做到这一点),也许是这样的用户不要奇怪这个名为etc
的愚蠢文件夹是什么,并尝试删除它。
在设备上,Apple决定将用户数据存储在/private/var/mobile
(用户名为“mobile”)。我不确定他们为什么不选择/Users/mobile
或仅/mobile
,但它在“正常”的Unix上没有比/var/mobile
更重要的意义。
在模拟器上,您的用户帐户无法写入/var
(有充分理由)。用户数据存储在~/Library/Application Support/iPhone Simulator
的某个位置。有一次,他们开始为不同的模拟器版本使用不同的目录。
答案 3 :(得分:3)
/var
只是/private/var
的符号链接。因此,第一个路径是您尝试访问的逻辑路径。第二个是扩展符号链接的相同路径。
答案 4 :(得分:0)
让fileURLs =试试fileManager.contentsOfDirectory(at:
它打印为/private/var
让DocumentDirURL =尝试! FileManager.default.url(用于:.documentDirectory,位于:.userDomainMask,适当于:无,创建:true)
它打印为/var
:)
答案 5 :(得分:0)
一项功能(快速5),用于从缓存中删除文件。我遇到了很多问题,使用URL解决了/ private问题。
class func removeFileFromCache( filePattern: String ) -> Bool {
// find filename with pattern
do {
let cachePath = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask).first!
let filePathUrl = URL( fileURLWithPath: filePattern )
let originalFilename = filePathUrl.lastPathComponent
let newFilePath = cachePath.appendingPathComponent( originalFilename ).path
try FileManager.default.removeItem(atPath: newFilePath )
print("file \( filePattern ) succesfull removed.",classname:URL(fileURLWithPath: #file).lastPathComponent )
} catch let error as NSError {
print("Error \(error)",classname:URL(fileURLWithPath: #file).lastPathComponent )
return false // all is not well
}
return true
}