I am attempting to create what should be a rather simple function, isInTrash, to return whether a file path passed to it points to a location in any trash. This thread https://developer.apple.com/forums/thread/110864 got me partway there, but the results I am getting don't match with what I expect.
Function:
func isInTrash(file: String) -> Bool {
guard let fileURL = URL(string: file) else {
return false
}
var relationship: FileManager.URLRelationship = .same
let defaultManager: FileManager = FileManager.default
do {
try defaultManager.getRelationship(&relationship,
of: FileManager.SearchPathDirectory.trashDirectory,
in: FileManager.SearchPathDomainMask(rawValue: 0),
toItemAt: fileURL)
} catch {
NSLog("Unable to get relationship of path to trash.:\n")
}
return relationship == .contains
}
Unit Test:
func testInTrashPaths() {
XCTAssertTrue(handler.isInTrash(file: "/Users/username/Trash/foo")) //fails
XCTAssertTrue(handler.isInTrash(file: "/Users/username/.Trash/foo")) //fails
XCTAssertTrue(handler.isInTrash(file: "/Users/username/.Trash/bar")) //fails
XCTAssertTrue(handler.isInTrash(file: "/Users/username/.Trash/blah")) //fails
XCTAssertTrue(handler.isInTrash(file: "/Users/username/.Trash/test/bang")) //fails
XCTAssertFalse(handler.isInTrash(file: "/Users/username/Desktop/test/bang")) //succeeds
}
The tests that should return true all fail. The negative test succeeds, but that's not really a surprise. If I switch to testing for .same instead of .contains, then the first Assert succeeds ("/Users/username/Trash/foo").
Two questions about that behavior.
- it appears that while the actual path, if you open the trash in a terminal and use pwd, is /.Trash, the api treats it as /Trash. Why?
- /Trash/foo returns .same instead of .contains. Why is it saying that a file inside the trash has a relationship of .same to the Trash? It's very clearly a contains relationship. What's going on?
If I sanitize the inputs by substituting "/" for "/." using replacingOccurrences(of:with:), then everything except the negative test fails. When I step through in the debugger, I find that now a path to a file on the desktop is returning .same for the Trash! WHAT!?!?!? WHY!?!?
I would dearly love to know what I'm doing wrong here.
I’m not sure if anything else is going on here but your isInTrash(…)
function has a serious bug. Specifically, this code is incorrect:
guard let fileURL = URL(string: file) else {
You should be using init(fileURLWithPath:)
. What you’re constructing here is as scheme-less URL that just contains a path. While you want is a URL with the file
scheme. Consider:
import Foundation
let u1 = URL(fileURLWithPath: "/Users/quinn/Test")
let u2 = URL(string: "/Users/quinn/Test")!
print(u1) // file:///Users/quinn/Test/
print(u2) // /Users/quinn/Test
Share and Enjoy
—
Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"