RepoPilotOpen in app →

Haneke/HanekeSwift

A lightweight generic cache for iOS written in Swift with extra love for images.

Mixed

Stale — last commit 5y ago

worst of 4 axes
Use as dependencyMixed

last commit was 5y ago; no tests detected

Fork & modifyHealthy

Has a license, tests, and CI — clean foundation to fork and modify.

Learn fromHealthy

Documented and popular — useful reference codebase to read through.

Deploy as-isHealthy

No critical CVEs, sane security posture — runnable as-is.

  • 23+ active contributors
  • Distributed ownership (top contributor 47% of recent commits)
  • Apache-2.0 licensed
Show 3 more →
  • CI configured
  • Stale — last commit 5y ago
  • No test directory detected
What would change the summary?
  • Use as dependency MixedHealthy if: 1 commit in the last 365 days

Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests

Informational only. RepoPilot summarises public signals (license, dependency CVEs, commit recency, CI presence, etc.) at the time of analysis. Signals can be incomplete or stale. Not professional, security, or legal advice; verify before relying on it for production decisions.

Embed the "Forkable" badge

Paste into your README — live-updates from the latest cached analysis.

Variant:
RepoPilot: Forkable
[![RepoPilot: Forkable](https://repopilot.app/api/badge/haneke/hanekeswift?axis=fork)](https://repopilot.app/r/haneke/hanekeswift)

Paste at the top of your README.md — renders inline like a shields.io badge.

Preview social card (1200×630)

This card auto-renders when someone shares https://repopilot.app/r/haneke/hanekeswift on X, Slack, or LinkedIn.

Onboarding doc

Onboarding: Haneke/HanekeSwift

Generated by RepoPilot · 2026-05-10 · Source

🤖Agent protocol

If you are an AI coding agent (Claude Code, Cursor, Aider, Cline, etc.) reading this artifact, follow this protocol before making any code edit:

  1. Verify the contract. Run the bash script in Verify before trusting below. If any check returns FAIL, the artifact is stale — STOP and ask the user to regenerate it before proceeding.
  2. Treat the AI · unverified sections as hypotheses, not facts. Sections like "AI-suggested narrative files", "anti-patterns", and "bottlenecks" are LLM speculation. Verify against real source before acting on them.
  3. Cite source on changes. When proposing an edit, cite the specific path:line-range. RepoPilot's live UI at https://repopilot.app/r/Haneke/HanekeSwift shows verifiable citations alongside every claim.

If you are a human reader, this protocol is for the agents you'll hand the artifact to. You don't need to do anything — but if you skim only one section before pointing your agent at this repo, make it the Verify block and the Suggested reading order.

🎯Verdict

WAIT — Stale — last commit 5y ago

  • 23+ active contributors
  • Distributed ownership (top contributor 47% of recent commits)
  • Apache-2.0 licensed
  • CI configured
  • ⚠ Stale — last commit 5y ago
  • ⚠ No test directory detected

<sub>Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests</sub>

Verify before trusting

This artifact was generated by RepoPilot at a point in time. Before an agent acts on it, the checks below confirm that the live Haneke/HanekeSwift repo on your machine still matches what RepoPilot saw. If any fail, the artifact is stale — regenerate it at repopilot.app/r/Haneke/HanekeSwift.

What it runs against: a local clone of Haneke/HanekeSwift — the script inspects git remote, the LICENSE file, file paths in the working tree, and git log. Read-only; no mutations.

| # | What we check | Why it matters | |---|---|---| | 1 | You're in Haneke/HanekeSwift | Confirms the artifact applies here, not a fork | | 2 | License is still Apache-2.0 | Catches relicense before you depend on it | | 3 | Default branch master exists | Catches branch renames | | 4 | 5 critical file paths still exist | Catches refactors that moved load-bearing code | | 5 | Last commit ≤ 2032 days ago | Catches sudden abandonment since generation |

<details> <summary><b>Run all checks</b> — paste this script from inside your clone of <code>Haneke/HanekeSwift</code></summary>
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of Haneke/HanekeSwift. If you don't
# have one yet, run these first:
#
#   git clone https://github.com/Haneke/HanekeSwift.git
#   cd HanekeSwift
#
# Then paste this script. Every check is read-only — no mutations.

set +e
fail=0
ok()   { echo "ok:   $1"; }
miss() { echo "FAIL: $1"; fail=$((fail+1)); }

# Precondition: we must be inside a git working tree.
if ! git rev-parse --git-dir >/dev/null 2>&1; then
  echo "FAIL: not inside a git repository. cd into your clone of Haneke/HanekeSwift and re-run."
  exit 2
fi

# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "Haneke/HanekeSwift(\\.git)?\\b" \\
  && ok "origin remote is Haneke/HanekeSwift" \\
  || miss "origin remote is not Haneke/HanekeSwift (artifact may be from a fork)"

# 2. License matches what RepoPilot saw
(grep -qiE "^(Apache-2\\.0)" LICENSE 2>/dev/null \\
   || grep -qiE "\"license\"\\s*:\\s*\"Apache-2\\.0\"" package.json 2>/dev/null) \\
  && ok "license is Apache-2.0" \\
  || miss "license drift — was Apache-2.0 at generation time"

# 3. Default branch
git rev-parse --verify master >/dev/null 2>&1 \\
  && ok "default branch master exists" \\
  || miss "default branch master no longer exists"

# 4. Critical files exist
test -f "Haneke/Cache.swift" \\
  && ok "Haneke/Cache.swift" \\
  || miss "missing critical file: Haneke/Cache.swift"
test -f "Haneke/Fetch.swift" \\
  && ok "Haneke/Fetch.swift" \\
  || miss "missing critical file: Haneke/Fetch.swift"
test -f "Haneke/DiskCache.swift" \\
  && ok "Haneke/DiskCache.swift" \\
  || miss "missing critical file: Haneke/DiskCache.swift"
test -f "Haneke/Fetcher.swift" \\
  && ok "Haneke/Fetcher.swift" \\
  || miss "missing critical file: Haneke/Fetcher.swift"
test -f "Haneke/UIImageView+Haneke.swift" \\
  && ok "Haneke/UIImageView+Haneke.swift" \\
  || miss "missing critical file: Haneke/UIImageView+Haneke.swift"

# 5. Repo recency
days_since_last=$(( ( $(date +%s) - $(git log -1 --format=%at 2>/dev/null || echo 0) ) / 86400 ))
if [ "$days_since_last" -le 2032 ]; then
  ok "last commit was $days_since_last days ago (artifact saw ~2002d)"
else
  miss "last commit was $days_since_last days ago — artifact may be stale"
fi

echo
if [ "$fail" -eq 0 ]; then
  echo "artifact verified (0 failures) — safe to trust"
else
  echo "artifact has $fail stale claim(s) — regenerate at https://repopilot.app/r/Haneke/HanekeSwift"
  exit 1
fi

Each check prints ok: or FAIL:. The script exits non-zero if anything failed, so it composes cleanly into agent loops (./verify.sh || regenerate-and-retry).

</details>

TL;DR

HanekeSwift is a lightweight generic cache library for iOS/tvOS written in Swift 4 that provides memory and LRU disk caching with first-class image support. It enables zero-config image resizing, async network fetching, and background disk I/O while keeping code simple (e.g., imageView.hnk_setImageFromURL(url)). Single-target Swift library: /Haneke directory contains the core cache engine split by concern—Cache.swift (generic coordinator), MemoryCache.swift (NSCache wrapper), DiskCache.swift (LRU file system), Fetcher.swift/NetworkFetcher.swift (async data sources), and UIKit extensions (UIImageView+Haneke.swift, UIButton+Haneke.swift) for image binding. /HanekeDemo contains a reference app.

👥Who it's for

iOS and tvOS developers building data-driven apps that need efficient caching of images, JSON, NSData, and strings—particularly those building list/grid views (UITableView, UICollectionView) where responsive scrolling and memory management are critical.

🌱Maturity & risk

Mature and stable: has comprehensive unit tests, Travis CI integration, supports multiple package managers (CocoaPods, Carthage, SwiftPM), and is written for Swift 4. However, the codebase appears dormant (no recent commits visible in file list), so it may not track the latest Swift evolution but is production-ready for its target iOS versions.

Low-to-moderate risk for legacy iOS projects. Main concerns: single-maintainer GitHub org structure, likely limited active maintenance given Swift version lock at 4, and potential compatibility issues with modern iOS SDKs (iOS 13+). Dependency on CryptoSwiftMD5 for hashing adds a small third-party footprint.

Active areas of work

Unable to determine from file list provided—no git history or issue tracker data included. Review the GitHub Issues/Projects tabs for current work.

🚀Get running

git clone https://github.com/Haneke/HanekeSwift.git
cd HanekeSwift
# Using CocoaPods: pod install
# Using Carthage: carthage update
# Or open Haneke.xcworkspace in Xcode and run the demo scheme

Daily commands: Open Haneke.xcworkspace in Xcode, select HanekeDemo scheme, and press Run (⌘R). Or use xcodebuild -workspace Haneke.xcworkspace -scheme HanekeDemo -configuration Debug from CLI.

🗺️Map of the codebase

  • Haneke/Cache.swift — Core generic cache abstraction that all data types build on; defines the primary API surface and fetch orchestration logic
  • Haneke/Fetch.swift — Defines the Fetch protocol and execution pipeline; essential for understanding how cache reads/writes and network operations are sequenced
  • Haneke/DiskCache.swift — Persistent storage layer managing file system operations; critical for understanding cache durability and eviction policies
  • Haneke/Fetcher.swift — Abstract fetcher protocol that NetworkFetcher and DiskFetcher implement; key extension point for custom data sources
  • Haneke/UIImageView+Haneke.swift — Primary UI integration showing how the cache integrates with iOS views; demonstrates the most common library usage pattern
  • Haneke/Haneke.swift — Module initialization and top-level cache instance management; entry point for library setup
  • Haneke/Format.swift — Image format and resizing logic; critical for understanding image-specific caching features and in-memory optimization

🧩Components & responsibilities

  • Cache<T> (Swift generics, DispatchQueue, Protocol composition) — Central orchestrator; manages fetch pipeline, delegates to memory/disk tiers, coordinates Fetcher execution
    • Failure mode: If fetch fails, returns nil; caller must handle graceful degradation (e.g., placeholder image)
  • DiskCache — Persistent file-based storage; enforces capacity limits via LRU eviction

🛠️How to make changes

Add a custom data fetcher for a new data source

  1. Create a new class conforming to Fetcher protocol in a new file (e.g., MyCustomFetcher.swift) (Haneke/Fetcher.swift)
  2. Implement fetch(key:failure:success:) to retrieve data from your source and call success/failure closures (Haneke/NetworkFetcher.swift)
  3. Pass your fetcher instance to cache.fetch(key:formatters:fetchers:failure:success:) in the fetchers array (Haneke/Cache.swift)

Add image caching with custom size formatting to a UIImageView

  1. Import Haneke and create a Format instance specifying desired image size (Haneke/Format.swift)
  2. Call imageView.hnk_setImageFromURL(_:placeholder:format:failure:success:) with your Format (Haneke/UIImageView+Haneke.swift)
  3. Optionally configure the named cache (e.g., Haneke.sharedImageCache.diskCapacity) before first use (Haneke/Haneke.swift)

Configure cache size limits and expiry

  1. Access the Haneke.sharedImageCache singleton or create a new Cache<T> instance (Haneke/Haneke.swift)
  2. Set diskCapacity (bytes) and diskCache.maxDiskCapacity on the cache instance (Haneke/DiskCache.swift)
  3. For HTTP caching, NetworkFetcher respects Cache-Control headers automatically; no extra configuration needed (Haneke/NetworkFetcher.swift)

Implement a data type cache (non-image) with custom serialization

  1. Define your data type (e.g., struct MyData: DictionarySerializable) and implement toDictionary/fromDictionary (Haneke/Data.swift)
  2. Create a fetcher returning your type; use Cache<MyData>(name:) to create a typed cache (Haneke/Cache.swift)
  3. Call cache.fetch(key:failure:success:) with your custom fetcher to populate the cache (Haneke/Fetch.swift)

🔧Why these technologies

  • Swift generics (Cache<T>) — Allows single cache implementation to handle any serializable type (UIImage, JSON, Data) without code duplication or type casting
  • Two-tier storage (memory + disk) — Memory for speed (<1ms hits), disk for persistence and capacity; balances performance and resource footprint
  • HTTPURLResponse header parsing — Respects server Cache-Control directives automatically; reduces redundant network requests and follows HTTP semantics
  • MD5 key hashing — Converts arbitrary URLs and keys into valid filesystem paths; enables safe cache key generation

⚖️Trade-offs already made

  • Single shared Haneke.sharedImageCache instance vs. per-controller caches

    • Why: Reduces code verbosity and memory waste from duplicate caching, but sacrifices per-screen cache isolation
    • Consequence: Simpler API for common use case (image loading); advanced users can create named Cache<UIImage> instances for fine-grained control
  • Synchronous disk reads on-demand (no background prefetch)

    • Why: Simpler implementation, no background thread coordination needed
    • Consequence: Disk cache hits block main thread briefly (~10ms); suitable for images but may not fit all data types
  • LRU eviction only; no TTL-based expiry

    • Why: Simplifies implementation; disk capacity limits are the primary constraint
    • Consequence: Old stale cache entries persist until capacity limit triggers eviction; users must manually clear if freshness is critical
  • Format-based resizing before cache store

    • Why: Stores only the exact size needed for UI, reducing disk footprint
    • Consequence: Different formats for same URL create separate cache entries; users must plan Format strategy carefully

🚫Non-goals (don't propose these)

  • Real-time cache invalidation or server push notifications
  • Peer-to-peer or distributed caching across devices
  • Encryption or security-sensitive data handling
  • Background/offline-first sync layer
  • Support for platforms other than iOS and tvOS

🪤Traps & gotchas

Swift 4 lock: .swift-version file enforces Swift 4 compiler—newer Xcode versions may have compatibility friction. Background I/O: DiskCache operations are async and happen off main thread; calling code must not assume synchronous disk reads. Memory warnings: Cache auto-evicts on UIApplicationDidReceiveMemoryWarningNotification—test memory pressure scenarios. Image resizing: UIImage+Haneke.swift performs CPU-intensive operations; large image queues can starve the disk I/O thread. No Codable support: Format protocol predates Swift's Codable (Swift 4.0), so JSON fetches use Haneke's custom Format, not JSONDecoder.

🏗️Architecture

💡Concepts to learn

  • LRU Eviction (Least Recently Used) — HanekeSwift's DiskCache uses LRU to evict oldest-accessed files when disk capacity is exceeded; understanding LRU guarantees memory efficiency without external config
  • Type-Erased Generics — Cache<T> uses Swift's generic constraints to support any type conforming to the Format protocol; this pattern allows a single cache implementation to work with JSON, String, UIImage, etc.
  • Two-Tier Cache (L1/L2) — Memory cache (NSCache) serves hot reads; disk cache (file system) backs cold misses—understanding why both tiers matter prevents naive single-tier replacements
  • Background Thread I/O — All disk operations run off main thread via GCD; violating this causes jank in scrolling views—critical for iOS responsiveness guarantees
  • Protocol-Oriented Fetching — Fetcher protocol abstracts network, disk, and custom sources; this allows NetworkFetcher and DiskFetcher to be swapped at runtime without Cache knowing the source
  • UIView Category Extensions — Haneke extends UIImageView and UIButton with lazy loading methods (hnk_setImageFromURL); this Objective-C category pattern in Swift enables ergonomic one-liner image binding
  • Memory Warning Lifecycle — Cache listens to UIApplicationDidReceiveMemoryWarning and auto-evicts; apps must understand this interrupt to avoid data loss during memory pressure
  • SDWebImage/SDWebImage — Objective-C era image caching library; HanekeSwift is its modern Swift successor with simpler API but narrower scope
  • onevcat/Kingfisher — Contemporary Swift image cache library (2015+) with similar UIImageView binding API; active competitor with more features (filter chains, source transitions)
  • ReactiveCocoa/ReactiveCocoa — Functional reactive programming framework for Swift/Objective-C; Haneke uses manual async patterns where ReactiveCocoa would use Signals/Observables
  • Quick/Quick — BDD testing framework for Swift; could modernize Haneke's test suite from XCTest to Quick+Nimble assertions

🪄PR ideas

To work on one of these in Claude Code or Cursor, paste: Implement the "<title>" PR idea from CLAUDE.md, working through the checklist as the task list.

Add comprehensive unit tests for UIImage+Haneke.swift extensions

The Haneke library provides image caching as a core feature, but HanekeTests lacks specific test coverage for UIImage+Haneke.swift and UIImageView+Haneke.swift. These extensions are critical for the library's main use case (image caching on iOS). Current test files cover Cache, DiskCache, and Fetcher generics, but image-specific functionality needs dedicated tests for format transformations, size operations, and UIView bindings.

  • [ ] Create HanekeTests/UIImageTests.swift with tests for UIImage+Haneke extensions (color space, size scaling, data serialization)
  • [ ] Create HanekeTests/UIImageViewTests.swift with tests for image loading, fetching, and placeholder behavior
  • [ ] Create HanekeTests/UIButtonTests.swift for UIButton+Haneke.swift extension coverage
  • [ ] Verify all image format transformations are tested (JPEG, PNG handling)
  • [ ] Add tests for memory/disk cache interaction with UIImageView

Migrate from Travis CI to GitHub Actions workflow

The repo still uses .travis.yml for CI, which is outdated. GitHub Actions is now the standard for GitHub-hosted projects and provides better integration, faster execution, and more maintainability. This modernization will improve contributor experience and ensure the build status badge reflects current infrastructure.

  • [ ] Create .github/workflows/ci.yml that runs tests for both iOS and tvOS targets (Haneke-iOS.xcscheme and Haneke-tvOS.xcscheme)
  • [ ] Configure workflow to test against multiple Swift versions (reference .swift-version file)
  • [ ] Add test coverage for Carthage and SwiftPM builds (repo supports both per README badges)
  • [ ] Set up code coverage reporting to Codecov or Codacy
  • [ ] Remove or deprecate .travis.yml after validating new workflow succeeds
  • [ ] Update README CI badge to point to GitHub Actions

Add Network Fetcher integration tests with mock HTTP responses

HanekeTests/NetworkFetcherTests.swift likely exists but appears missing from the file list. The NetworkFetcher.swift handles remote URL image caching, which is complex with network I/O, redirects, and cache headers (NSHTTPURLResponse+Haneke.swift). Comprehensive mocking tests are needed to verify behavior without making real network calls and to test edge cases like 304 Not Modified responses.

  • [ ] Create HanekeTests/NetworkFetcherTests.swift with URLSession mock/stub implementation
  • [ ] Add tests for HTTP cache header handling (via NSHTTPURLResponse+Haneke.swift extension)
  • [ ] Test 304 Not Modified, redirect (301/302), and error responses (4xx, 5xx)
  • [ ] Add tests for concurrent network requests and cancellation
  • [ ] Verify integration with DiskCache for persistent caching of network images
  • [ ] Test timeout and network failure scenarios

🌿Good first issues

  • Add unit tests for CGSize+Swift.swift—the file exists but is not mentioned in test coverage; implement tests for aspect-ratio scaling logic.
  • Improve Log.swift with configurable log levels (debug, info, warning, error)—currently appears to have basic logging; add a public Haneke.logLevel config.
  • Add comprehensive example in Haneke.playground for custom Fetcher implementation—the playground exists but only shows basic JSON cache; add a 'custom markdown fetcher' walkthrough.

Top contributors

Click to expand

📝Recent commits

Click to expand
  • a2e8e5b — Merge pull request #444 from AccioSupport/master (joanromano)
  • c23bb97 — Update to Swift 5.0 & add SwiftPM badge (Jeehut)
  • ebbe2d6 — [README] Document support & installation via Accio (Jeehut)
  • 19f2a6c — Add basic SwiftPM manifest file (Jeehut)
  • 41c1efc — Merge pull request #448 from GreenlightMe/feature/swift-5 (joanromano)
  • 1f27e3a — Fixed minor bug (kevnm67)
  • c21c1c5 — Updated to swift 5 and fixed all warnings. (kevnm67)
  • 51efaca — Merge pull request #436 from aporat/master (joanromano)
  • ec058bf — Update .travis.yml (aporat)
  • 4d48a3e — xcode 10 + swift 4.2 (Adar Porat)

🔒Security observations

HanekeSwift is a caching library with generally good security posture, but has notable concerns: (1) Use of MD5 hashing is the primary issue - needs replacement with modern algorithms; (2) Disk cache lacks apparent encryption for sensitive data; (3) Network request handling should include comprehensive URL validation to prevent SSRF; (4) No visible security header validation in HTTP responses. The library is well-structured for a caching solution, but security-sensitive operations need hardening, particularly around cryptographic operations and data protection at rest.

  • High · Use of MD5 for Hashing — Haneke/CryptoSwiftMD5.swift. The codebase contains a CryptoSwiftMD5.swift file, indicating MD5 is being used for cryptographic purposes. MD5 is cryptographically broken and should not be used for security-sensitive operations like password hashing or data integrity verification. It is vulnerable to collision attacks. Fix: Replace MD5 with a modern, secure hashing algorithm such as SHA-256 or bcrypt for password hashing. If MD5 is only used for cache key generation (non-security context), document this clearly and consider using SHA-256 instead for consistency.
  • Medium · Potential Unvalidated URL Handling in NetworkFetcher — Haneke/NetworkFetcher.swift. The NetworkFetcher.swift file suggests network requests are being made. Without seeing the implementation, there's a risk of insufficient URL validation, which could lead to SSRF (Server-Side Request Forgery) vulnerabilities if user-controlled URLs are not properly validated before making network requests. Fix: Implement strict URL validation: whitelist allowed domains/protocols, reject file:// and other dangerous schemes, validate URL format, and implement timeout settings for network requests.
  • Medium · Potential Insecure Cache Storage — Haneke/DiskCache.swift. DiskCache.swift suggests cached data is stored on disk. If sensitive data (API responses, user information) is cached without encryption, it could be accessible to other applications or malicious actors with device access. Fix: Implement encryption for sensitive cached data using platform-provided APIs (e.g., Keychain on iOS). Add configuration options to allow users to specify which data should be encrypted. Use secure file permissions to restrict access to cache directories.
  • Low · Missing Security Headers Documentation — Haneke/NSHTTPURLResponse+Haneke.swift. Files like NSHTTPURLResponse+Haneke.swift suggest HTTP response handling. The codebase should validate security headers from network responses, but there's no visible documentation about security header validation. Fix: Implement validation of security-relevant HTTP headers (Content-Security-Policy, X-Content-Type-Options, etc.). Document security best practices for using the library with network requests.
  • Low · No Visible Dependency Pinning — Cartfile, Cartfile.resolved, Package.swift. While Cartfile and Package.swift are present, the actual dependency versions and their security status are not visible in the provided file structure. Unpinned or outdated dependencies could introduce vulnerabilities. Fix: Ensure all dependencies are pinned to specific, tested versions. Regularly audit dependencies using tools like OWASP Dependency-Check. Keep dependencies updated with security patches. Document minimum version requirements for security-critical dependencies.

LLM-derived; treat as a starting point, not a security audit.


Generated by RepoPilot. Verdict based on maintenance signals — see the live page for receipts. Re-run on a new commit to refresh.

Mixed signals · Haneke/HanekeSwift — RepoPilot