Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Empty Trash Bin via Objective-C/Cocoa

I was wondering if there is a way to programmatically empty the contents of the trash bin. I'm currently deleting files that are located there using:

    NSFileManager *manager = [NSFileManager defaultManager];
    [manager removeItemAtPath:fileToDelete error:nil];

However, after I use this operation, every time I drag a file to the trash, I am prompted with the message:

Are you sure you want to delete “xxxxxx.xxx”?This item will be deleted immediately. You can’t undo this action.

This lasts until I either log out or sudo rm -rf the trash bin.

Thanks!

like image 538
minimalpop Avatar asked Jan 21 '23 05:01

minimalpop


2 Answers

You could try using AppleScript to do it:

NSString* appleScriptString = @"tell application \"Finder\"\n"
                              @"if length of (items in the trash as string) is 0 then return\n"
                              @"empty trash\n"
                              @"repeat until (count items of trash) = 0\n"
                              @"delay 1\n"
                              @"end repeat\n"
                              @"end tell";
NSAppleScript* emptyTrashScript = [[NSAppleScript alloc] initWithSource:appleScriptString];

[emptyTrashScript executeAndReturnError:nil];
[emptyTrashScript release];
like image 114
David Avatar answered Jan 28 '23 07:01

David


You can put stuff in the trash with NSWorkspace, however deleting the trash is kind of a no no for programs so you aren't going to find an API. So your best bet is using the ScriptBridge.

Add ScriptingBridge.framework to your build target, and generate a header file for Finder using:

sdef /System/Library/CoreServices/Finder.app/ | sdp -fh --basename Finder

Then you can ask Finder to prompt the user to empty the trash:

#import "Finder.h"

FinderApplication *finder = [SBApplication applicationWithBundleIdentifier:@"com.apple.Finder"];

// activate finder
[finder activate];

// wait a moment (activate is not instant), then present alert message
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
  [finder emptySecurity:security];
});

See the Scripting Bridge documentation for more details.


As of Xcode 7.3, if you attempt this with Swift you will get linker errors trying to find classes defined in Finder.h. So you'll have to create an Objective-C wrapper.

like image 29
jbtule Avatar answered Jan 28 '23 07:01

jbtule