Skip to content

Instantly share code, notes, and snippets.

@kkebo
Last active May 1, 2023 14:09
Show Gist options
  • Save kkebo/c704a2b1624d5c3bef1da78d9821e005 to your computer and use it in GitHub Desktop.
Save kkebo/c704a2b1624d5c3bef1da78d9821e005 to your computer and use it in GitHub Desktop.
`ContentView` reads child files recursively when you drag and drop a directory.
struct ContentView: View {
@State private var isTargeted = false
var body: some View {
Rectangle()
.fill(self.isTargeted ? .green : .white)
.frame(maxWidth: .infinity, maxHeight: .infinity)
.onDrop(of: [.directory], isTargeted: self.$isTargeted) { providers in
for provider in providers {
_ = provider.loadFileRepresentation(for: .directory, openInPlace: true) { url, _, _ in
guard let url else { fatalError() }
guard url.startAccessingSecurityScopedResource() else { fatalError() }
defer { url.stopAccessingSecurityScopedResource() }
do {
try loadItems(at: url)
print("successfully loaded")
} catch {
print(error.localizedDescription)
}
}
}
return true
}
}
func loadItems(at url: URL) throws {
let enumerator = FileManager.default.enumerator(
at: url,
includingPropertiesForKeys: nil,
options: [],
errorHandler: nil
)
while let item = enumerator?.nextObject() as? URL {
if !item.hasDirectoryPath {
let data = try Data(contentsOf: item)
print("\(item.absoluteString) is \(data.count) bytes")
}
}
}
}
@kkebo
Copy link
Author

kkebo commented Apr 30, 2023

Modern version:

struct DirectoryItem: Codable, Transferable {
    let url: URL

    static var transferRepresentation: some TransferRepresentation {
        FileRepresentation(importedContentType: .directory, shouldAttemptToOpenInPlace: true) { received in
            .init(url: received.file)
        }
    }
}

struct ContentView: View {
    @State private var isTargeted = false

    var body: some View {
        Rectangle()
            .fill(self.isTargeted ? .green : .white)
            .frame(maxWidth: .infinity, maxHeight: .infinity)
            .dropDestination { (items: [DirectoryItem], _) in
                for url in items.map(\.url) {
                    guard url.startAccessingSecurityScopedResource() else { fatalError() }
                    defer { url.stopAccessingSecurityScopedResource() }
                    do {
                        try loadItems(at: url)
                        print("successfully loaded")
                    } catch {
                        print(error.localizedDescription)
                    }
                }
                return true
            } isTargeted: {
                self.isTargeted = $0
            }
    }

    func loadItems(at url: URL) throws {
        let enumerator = FileManager.default.enumerator(
            at: url,
            includingPropertiesForKeys: nil,
            options: [],
            errorHandler: nil
        )
        while let item = enumerator?.nextObject() as? URL {
            if !item.hasDirectoryPath {
                let data = try Data(contentsOf: item)
                print("\(item.absoluteString) is \(data.count) bytes")
            }
        }
    }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment