Properly move an object to the Trash
Asked Answered
M

1

9

It looks like on Cocoa there are many ways to move file/folder-directory to Trash:

  1. [[[NSWorkspace sharedWorkspace] performFileOperation:NSWorkspaceRecycleOperation]
  2. [[NSWorkspace sharedWorkspace] recycleURLs:]
  3. [NSFileManager trashItemAtURL:]
  4. [NSFileManager removeItemAtPath:]
  5. [NSFileManager removeItemAtURL:]

It would be nice to understand what the difference is by either reading an explanation here or a link to the official Apple docs.

Also if someone knows a universal way of moving a file/non-empty directory to Trash, it would be nice to know.

Murmurous answered 2/12, 2015 at 3:54 Comment(0)
U
11
  1. [[[NSWorkspace sharedWorkspace] performFileOperation:NSWorkspaceRecycleOperation]

This is deprecated, as of OS X 10.11, so no point in using it.

  1. [[NSWorkspace sharedWorkspace] recycleURLs:]

This is probably the one you want. It's asynchronous, so your application can continue to operate while the files are being moved to the trash.

  1. [NSFileManager trashItemAtURL:]

This is similar to option 2, but it's synchronous, and only handles one file at a time.

  1. [NSFileManager removeItemAtPath:]

This doesn't trash the file, it deletes it permanently, and immediately.

  1. [NSFileManager removeItemAtURL:]

This is just like option 4, except using a file:// URL instead of a path. More-convenient when you already have a URL rather than a path.

The reference pages for NSWorkspace and NSFileManager cover all of the differences between these methods fairly well.


Here's a quick sample, which uses recycleUrls: to delete a file or folder named "Junk" on the user's desktop:

- (IBAction)deleteJunk:(id)sender {
    NSFileManager *manager = [NSFileManager defaultManager];
    NSURL *url = [manager URLForDirectory:NSDesktopDirectory inDomain:NSUserDomainMask appropriateForURL:nil create:NO error:nil]; // get Desktop folder
    url = [url URLByAppendingPathComponent:@"Junk"]; // URL to a file or folder named "Junk" on the Desktop
    NSArray *files = [NSArray arrayWithObject: url];
    [[NSWorkspace sharedWorkspace] recycleURLs:files completionHandler:^(NSDictionary *newURLs, NSError *error) {
        if (error != nil) {
            //do something about the error
            NSLog(@"%@", error);
        }
        for (NSString *file in newURLs) {
            NSLog(@"File %@ moved to %@", file, [newURLs objectForKey:file]);
        }
    }];
}
Ungenerous answered 2/12, 2015 at 4:28 Comment(13)
1. I need the code that will work in 10.6+. 2. Is solution number 2 will work for both file(s) and non-empty directory? I will check those references as well. And can you put some sample code to trash the directory?Murmurous
recycleUrls: is available in OS X 10.6 and later. I added some sample code to my answer.Ungenerous
I am getting an error on the line "NSArray *files = @[url];". Googling says that I need the latest LLVM, which I don't have. I am on the 10.6 with XCode 4.2. How do I rewrite this line? Thx.Murmurous
I changed it to old-school Objective-C notation. Hope that helps.Ungenerous
are both options 2 and 3 accepts wildcards? And option 3 can send the directory and not just file, right? And options 3 is also 10.6+, right? Thank you.Murmurous
OK, I looked it up and it appears that "trashItemAtURL" is 10.8+. Prior to 10.8 I can use "FSPathMoveObjectToTrashSync". Unfortunately the function documentation is not available anymore. Does this mean I'm out of luck? I found this: #2852703 but I need a documentation in order to know what to pass to the function. Besides the function might be Carbon only and not be supported under Cocoa.Murmurous
2 option will display finder progressSidky
Careful with recycleURLs:! When you try to recycle a lot of items (in the 1000s), this can lead to a crash because it'll start a lot of concurrent threads.Munroe
@MarkBessey, sorry for the long delay. How do I check for possible errors?Murmurous
@ThomasTempelmann, sorry for the long delay. How do I check for a possible errors?Murmurous
@Murmurous Check for errors when doing what exactly? Whatever deletion function you use, they all come with some sort of error reporting. Also, the crash I warned about was happening in macOS 10.12 and 10.13 but was apparently fixed in 10.14 and later. Also, you can edit your comments. Or delete them and rewrite them if you made a mistake. This is not a chat site ;)Munroe
@thomastempelman, what i mean is - someone will be calling the function above to move stuff to trash, right? I need error checking in that caller...Murmurous
You can't check for errors at the time you call the function for recycleURLs: - that's what the completionHandler block is for. It'll get called at the end of the process, and can report errors to the user at that point, if desired. If you used trashItemAtURL:, it ruturns an error object, which you can inspect at that time.Ungenerous

© 2022 - 2024 — McMap. All rights reserved.