Image repository for Apple platforms, designed to complement SwiftData.
Persists a lightweight ImageSource value in SwiftData and resolves the actual image at display time by routing to the appropriate backend:
- Local images →
FileStorage(disk-backed,NSCachein-memory layer) - Remote images → Nuke
ImagePipeline(memory-decoded cache + disk cache + network)
- iOS 16+, macOS 13+, tvOS 16+, watchOS 9+, visionOS 1+
- Swift 6
Add the package via Swift Package Manager:
.package(url: "https://github.com/inesbcode/swift-image-repository", from: "1.0.0")Then add ImageRepository as a dependency of your target:
.target(
name: "MyApp",
dependencies: [
.product(name: "ImageRepository", package: "swift-image-repository"),
]
)For test or Xcode Preview targets only, you can also add ImageRepositoryMocks.
let repository = ImageRepository()
let source = try repository.store(imageData) // ImageSource.local(id)
photo.imageSource = source // persist the ImageSource in SwiftDatalet image = try await repository.fetch(photo.imageSource)For .local sources, FileStorage serves the image from its NSCache or disk. For .remote sources, Nuke's ImagePipeline handles memory cache, disk cache, and network transparently.
try repository.delete(photo.imageSource)Removes local files from disk and evicts remote entries from Nuke's memory and disk cache.
try repository.clean()let repository = ImageRepository(subsystem: "com.myapp.images")All log events are routed through the Logging instance and are visible in Console.app and log stream under the configured subsystem.
ImageRepositoryMocks provides MockImageRepository and MockImagePipeline for use in unit tests and Xcode Previews. Add the target only to test or preview targets — never to a production app target.
import ImageRepositoryMocks
// Stub a successful remote fetch
let mock = MockImageRepository()
mock.remoteFetchResult = UIImage(named: "placeholder")!
// Inject an error
mock.fetchStub = .imageNotFound("test-id")
// Verify call counts
#expect(mock.storeCallCount == 1)ImageSource (SwiftData-persisted)
├── .local(id) → FileStorage (NSCache + disk)
└── .remote(url) → ImagePipeline / Nuke (memory + disk + network)
ImageRepository conforms to ImageRepositoryProtocol, so it can be substituted with MockImageRepository in tests without changing call sites.
MIT