An iOS app that fetches and displays random anime quotes — built for anime lovers who want a fresh quote every time they open the app or pull to refresh. Originally published on the App Store in 2021, and actively developed through 2025 with a full architectural overhaul. No longer available following developer account closure.
Tech Stack: Swift, UIKit, async/await, URLSession, Coordinators, Codable, UITabBarController, UserDefaults, Accessibility
The app was significantly rebuilt after the initial 1.0 release:
- Migrated from Alamofire to URLSession + async/await — removed the third-party dependency and rewrote the networking layer using Swift Concurrency
- Updated API — adapted to a new API response format (
animechan.io v1), requiring a new model layer (AnimeResponse,AnimeQuoteData,AnimeInfo,CharacterInfo) that maps to the originalAnimeDataModel - Daily quote caching —
NetworkServiceuses UserDefaults to persist the day's quote, so the same quote shows throughout the day and a new one is fetched the next - QuoteService abstraction — introduced a service layer to route between free and premium API endpoints, keeping networking logic out of the view controller
- Settings screen — built a full
SettingsVCwith a programmatic groupedUITableView, three custom cell types (SwitchCell,ButtonCell,InfoCell), and a data-driven section model. Includes premium API toggle, dark mode toggle (premium-gated), upgrade flow, privacy policy, and live app version display - Tab bar architecture — refactored from a single-screen coordinator to a full
UITabBarControllerwith three tabs (Quotes, Shout Outs, Settings), each with its own coordinator and navigation controller - AppearanceManager — centralized global UI styling (tab bar transparency, tint colour, translucency) into a singleton, keeping appearance logic out of AppDelegate
- Error handling — added a typed
NetworkErrorenum (invalidURL,noData,decodingError) with user-facing alerts and a Retry action - BundleExtension — version string utility reading
CFBundleShortVersionStringandCFBundleVersion, with environment scheme detection for dev/staging builds
- Random anime quotes fetched on launch and pull-to-refresh
- Daily quote caching — same quote shown throughout the day, new quote on next day
- Settings screen with premium toggle, dark mode toggle, upgrade flow, and privacy policy
- Three-tab navigation: Quotes, Shout Outs, Settings
- Shout Outs screen credits the API creator and photographer with tappable SafariServices links
- VoiceOver accessibility support including the Z gesture to dismiss the Shout Outs screen
- Typed error handling with user-facing retry alerts
- SwiftLint configured throughout
App
├── AppCoordinator — root coordinator, sets up UITabBarController
├── AnimeQuotesTabCoordinator
│ └── AnimeQuotesVC — fetches quotes via QuoteService, renders in UITableView
├── ShoutOutsTabCoordinator
│ └── ShoutOutsVC — credits screen with SafariServices + VoiceOver Z gesture
├── SettingsTabCoordinator
│ └── SettingsVC — programmatic grouped UITableView with custom cells
│
├── QuoteService — routes to free or premium endpoint based on UserDefaults
├── NetworkService — URLSession + async/await, daily caching via UserDefaults
├── AppearanceManager — global tab bar and UI styling singleton
└── BundleExtension — version string utility with environment detection
- async/await networking — migrated away from Alamofire to native Swift Concurrency;
fetchData()usesURLSession.shared.data(from:)with structured error propagation - API versioning — when the upstream API changed its response shape, a new nested model layer was introduced to decode the new format while preserving the existing
AnimeDataModelused throughout the UI - Data-driven Settings —
SettingsSection/SettingsItemmodels drive the entire settings table; adding a new row is a one-line change to the section array - Coordinator memory management —
childDidFinish(_:)cleans up child coordinators on back navigation viaUINavigationControllerDelegate - Per-tab coordinators — each tab owns its own
UINavigationControllerand coordinator, keeping navigation logic fully isolated between screens
MIT — feel free to use this project, but please change the UI (colours, fonts, images, layout) if redistributing.


