Is it safe to mark the FileManager Sendable?

Viewed 36

I have an extension on the FileManager that uses the new concurrency: try await Task.detached(priority: .background) closure and then uses self to create a directory enumerator with FileManager.enumerator(at:includingPropertiesForKeys:options:errorHandler:).

On Xcode 14 I get the warning: enter image description here

I am trying to figure out if it's safe to mark FileManager as Sendable:
extension FileManager: @unchecked Sendable {}.

It seems that FileManager is thread safe with some caveats: The methods of the shared FileManager object can be called from multiple threads safely.

Any reason why Apple did not mark the FileManager as Sendable? I would think they have a reason not to do that in which case I should definitely avoid marking it sendable, or maybe they just did not get to it?

Full code (adapted from src):

func allocatedSizeOfDirectory(at directoryURL: URL) async throws -> UInt64 {
    try await Task.detached(priority: .background) {
        // The error handler simply stores the error and stops traversal
        var enumeratorError: Error?
        func errorHandler(_: URL, error: Error) -> Bool {
            guard (error as NSError).code != NSFileReadNoPermissionError else { return true }
            enumeratorError = error
            return false
        }

        // We have to enumerate all directory contents, including subdirectories.
        let enumerator = self.enumerator(at: directoryURL,
                                         includingPropertiesForKeys: Array(allocatedSizeResourceKeys),
                                         options: [],
                                         errorHandler: errorHandler)!

        // We'll sum up content size here:
        var accumulatedSize: UInt64 = 0

        // Perform the traversal.
        for item in enumerator {

            // Bail out on errors from the errorHandler.
            if enumeratorError != nil { break }

            // Add up individual file sizes.
            let contentItemURL = item as! URL
            accumulatedSize += try contentItemURL.regularFileAllocatedSize()
        }

        // Rethrow errors from errorHandler.
        if let error = enumeratorError { throw error }

        return accumulatedSize
    }.value
}
0 Answers
Related