Introducing FZMetadata, a Framework for File Metadata & File Query similar to Spotlight

I created an open source framework for File Metadata & File Query similar to Spotlight.

Github: FZMetadata
Documentation: Online


MetadataItem lets you access the metadata of a file.

let videoFile = URL(filePathWithString: pathToFile)
if let metadata = videoFile.metadata {
    let videoDuration = metadata.duration
    let lastUsedDate = metadata.lastUsedDate
    let videoResolution = metadata.pixelSize


A file query that provides:

  • Blazing fast search of files simliar to Spotlight by predicate and attributes like file name, file size, last used date, video duration, etc.
  • Blazing fast query of attributes for large batches of files.
  • Monitoring of files and directories for updates to the search results.

Searching for files by location & predicate

The results handler gets called whenever new files meet the specified predicate at the search locations.

let query = MetadataQuery()
query.searchLocations = [.downloadsDirectory, .documentsDirectory]

 // Image & videos files, added this week, large than 10mb
query.predicate = { 
    $0.fileTypes(.image, .video) && 
    $0.dateAdded.isThisWeek && 
    $0.fileSize.megabytes >= 10 
query.resultsHandler = { files, _ in
// found files

Query of file attributes

MetadataQuery provides blazing fast query of file metadata attributes for large batches of files. Fetching attributes for thousands of files often takes less than a second.

// URLs for querying of attributes
query.urls = videoFileURLs 

// Metadata attributes to query
query.attributes = [.pixelSize, .duration, .fileSize, .creationDate]

query.resultsHandler = { files, _ in  
    for file in files {
    // file.pixelSize, file.duration, file.fileSize, file.creationDate

Monitoring of files & directories

MetadataQuery can monitor for changes to search results & queried attributes. It calls the completionHandler whenever changes happen.

To enable monitoring use enableMonitoring().

// Files that are screenshots.
query.predicate = { $0.isScreenCapture }

// Searches everywhere on the local file system.
query.searchScopes = [.local]

// Enables monitoring. Whenever a new screenshot gets captures the completion handler gets called.

query.resultsHandler = { files, _ in  
    for file in files {
    // screenshot files