问题描述
有一个similar question for iOS,但我发现推荐的解决方案并非在所有情况下都适用于macOS。
在Mac上,可能有很多“垃圾箱”文件夹:
-
/.Trashes
-
~/.Trash
-
~/Library/Mobile Documents/com~apple~CloudDocs/.Trash
–这是来自iCloud -
/Users/xxx/.Trash
–任何其他用户的垃圾桶 -
/Volumes/xxx/.Trashes
此代码应该有效,但不适用于iCloud垃圾箱:
NSURL *theURL = ...;
NSURLRelationship relationship = NSURLRelationshipOther;
NSError *error = nil;
[NSFileManager.defaultManager
getRelationship: &relationship
ofDirectory: NSTrashDirectory
inDomain: 0
toItemAtURL: theURL
error: &error];
BOOL insideTrash = !error && (relationship == NSURLRelationshipContains);
如果URL指向任何iCloud文件夹(包括上面显示的“垃圾箱”文件夹),则会出现此错误:
Error Domain=NSCocoaErrorDomain Code=3328
"The requested operation couldn’t be completed because the feature is not supported."
奇怪的是,即使10.15 SDK中的“ NSFileManager”头文件也建议使用相同的代码:
/* trashItemAtURL:resultingItemURL:error: [...]
To easily discover if an item is in the Trash,you may use
[fileManager getRelationship:&result ofDirectory:NSTrashDirectory
inDomain:0 toItemAtURL:url error:&error]
&& result == NSURLRelationshipContains.
*/
似乎还有一个issue with trashItemAtURL:
on iCloud-synched folders。
那么,我该如何解决呢?如果Finder可以检测到iCloud垃圾,我也应该可以。
(注意:我用于测试的应用程序甚至都没有沙盒化处理)
更多发现:符号链接也失效
如果URL指向目标不存在的符号链接,则正式建议的使用getRelationship:
的方法也会失败并显示错误。
因此,基本上,此功能已被破坏(已在10.13.6、10.15.7和11.0.1中进行验证)。
下面是演示该错误的代码,我已将其提交给FB8890518,并提交给Apple:
#import <Foundation/Foundation.h>
static void testSymlink (NSString* symlinkName,NSString* symlinkTarget)
{
NSString *path = [[NSString stringWithFormat:@"~/.Trash/%@",symlinkName] stringByExpandingTildeInPath];
NSURL *url = [NSURL fileURLWithPath:path];
symlink (symlinkTarget.UTF8String,path.UTF8String);
NSLog(@"created symlink at <%@> pointing to <%@>",url.path,symlinkTarget);
NSURLRelationship relationship = -1;
NSError *error = nil;
[NSFileManager.defaultManager getRelationship:&relationship ofDirectory:NSTrashDirectory inDomain:0 toItemAtURL:url error:&error];
NSString *rel = @"undetermined";
if (relationship == 0) rel = @"NSURLRelationshipContains";
if (relationship == 1) rel = @"NSURLRelationshipSame";
if (relationship == 2) rel = @"NSURLRelationshipOther";
NSLog(@"result:\n relationship: %@\n error: %@",rel,error);
}
int main(int argc,const char * argv[])
{
@autoreleasepool {
testSymlink (@"validSymlink",@"/System");
testSymlink (@"brokenSymlink",@"/nonexisting_file");
}
return 0;
}
解决方法
意识到[NSFileManager getRelationship:]
甚至因符号链接损坏而失败,我得出结论,这是macOS中的一个错误,多年来一直未发现。
我想出了以下解决方法:
使用getRelationship:
操作,然后首先检查返回的错误:
- 如果没有错误,请检查
relationship == NSURLRelationshipContains
,并将其用作我的结果。 - 否则,如果发生任何错误,请检查路径中是否包含“ /.Trash/”或“ /.Trashes/”-如果是,则假定该项目位于“垃圾箱”文件夹中。
NSURL *theURL = ...;
NSURLRelationship relationship = NSURLRelationshipOther;
NSError *error = nil;
[NSFileManager.defaultManager
getRelationship: &relationship
ofDirectory: NSTrashDirectory
inDomain: 0
toItemAtURL: theURL
error: &error];
BOOL insideTrash = !error && (relationship == NSURLRelationshipContains)
|| error && (
[theURL.path containsString:@"/.Trash/"]
|| [theURL.path containsString:@"/.Trashes/"]
)
);