Skip to content

inesbcode/swift-image-repository

Repository files navigation

swift-image-repository

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 imagesFileStorage (disk-backed, NSCache in-memory layer)
  • Remote images → Nuke ImagePipeline (memory-decoded cache + disk cache + network)

Requirements

  • iOS 16+, macOS 13+, tvOS 16+, watchOS 9+, visionOS 1+
  • Swift 6

Installation

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.

Usage

Store a local image

let repository = ImageRepository()
let source = try repository.store(imageData)  // ImageSource.local(id)
photo.imageSource = source  // persist the ImageSource in SwiftData

Fetch an image

let 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.

Delete an image

try repository.delete(photo.imageSource)

Removes local files from disk and evicts remote entries from Nuke's memory and disk cache.

Clear all images

try repository.clean()

Custom subsystem for logging

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.

Mocks

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)

Architecture

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.

License

MIT

About

Image repository for Apple platforms, designed to complement SwiftData.

Topics

Resources

License

Stars

Watchers

Forks

Contributors

Languages