MediaCleaner is an iOS app for scanning the user's photo library, finding visually similar or duplicate photos, and helping the user review which images to keep or remove.
The project is written in Swift with SwiftUI, PhotoKit, Vision, and Core Data. The current codebase focuses on one feature end to end: a scanner flow that requests photo-library access, indexes assets, analyzes similarity, shows duplicate groups, and supports review/deletion from a detail screen.
- SwiftUI app shell with dependency composition and a single scanner-focused root flow.
- PhotoKit authorization, asset fetch, thumbnail loading, and asset deletion APIs.
- Core Data-backed indexing of photo metadata to support incremental rescans.
- Vision-based duplicate detection using feature prints.
- Metadata prefiltering and time-based slice splitting before expensive Vision work.
- Parallel extraction workers for image loading and feature-print generation.
- Post-group quality scoring to recommend which photo to keep in a duplicate group.
- Live scan progress, logging, diagnostics, and memory snapshots for long scans.
- Duplicate groups list, sorting, preview UI, and full-screen group detail review.
- Batch delete flow from the detail screen.
- Unit and contract tests for domain helpers, scanner presentation state, logging, persistence, and detector contracts.
The scanner currently works like this:
- Request or validate Photo Library permission.
- Fetch all image assets from the user's library.
- Rebuild the metadata index in Core Data.
- Pre-filter assets into coarse buckets using metadata such as aspect ratio and megapixel bucket.
- Split large buckets into narrower time-window slices.
- Extract Vision feature prints for slice candidates.
- Compare feature prints and build duplicate groups.
- Run quality scoring on grouped assets to recommend a keep candidate.
- Present final groups in the UI and allow review/deletion.
The code is organized by feature and responsibility:
MediaCleaner/AppApp entry point, composition root, container, logging.MediaCleaner/Features/ScannerScanner UI, flow state, presentation models, detail screen.MediaCleaner/Services/PhotoLibraryPhotoKit authorization, fetch, delete, thumbnail loading.MediaCleaner/Services/IndexingAsset metadata indexing and incremental rescan support.MediaCleaner/Services/AnalysisVision duplicate detection pipeline, slice processing, grouping, quality scoring.MediaCleaner/DataCore Data persistence and scan cache storage.MediaCleaner/DomainModels, protocols, and pure helpers shared across the app.MediaCleanerTestsUnit and contract tests.
- The scanner feature uses a single flow-oriented view model rather than many small screen view models.
VisionDuplicateDetectoracts as an orchestrator; prefilter/report support and slice processing are split into helper modules for readability.- Expensive image quality scoring is intentionally performed after grouping, not during early extraction, so the app scores only assets that actually end up in duplicate groups.
- Current deployment target in the project file is iOS
26.2. - In
DEBUGbuilds, photo deletion is simulated byPhotoLibraryServiceinstead of physically removing assets. - The app currently focuses on the scanner flow; there is no broader settings/onboarding/account feature set yet.

