Skip to content

Repository files navigation

Quotes

A SwiftUI app that allows users to record their thoughts on a quote daily. Each day a new quote is displayed via the Zen Quotes API.

⚙️ Features

  • The app displays a new quote every day via the API in the 'Home' tab. The user can then choose to share this quote with other apps or reflect on the quote and save their thoughts/feelings.
  • Quotes which have been reflected upon will appear in the 'Saved' tab. The user can scroll through the list of their saved quotes or search by author or quote content. Each quote's reflection can be viewed or edited from here. Each quote can be deleted from the menu button or by swipe action.
  • In the 'Settings' tab the user can change their notifications and appearance settings. The notification reminds them to open the app each day to see a new quote (assuming the user has granted permission to receive notifications). The user can switch between light, dark and system appearance.

🔍 Technical details

Overview:

  • This app is almost entirely SwiftUI. UIKit was used for the UIActivityViewController on iPad.
  • The minimum deployment target is iOS 27.0 and iPadOS 27.0.
  • Swift language version is Swift 6.
  • MVVM, Core Data and Swift concurrency.
  • iPhone and iPad are both supported.
  • The app supports different size classes, portrait and landscape orientation, and light, dark or system appearance.
  • XCTest and Swift Testing are used for testing.

Networking:

  • The network code uses async/await with URLSession, and there is dependency injection for loose coupling and testability.
  • The network response is cached using URLCache.
  • The caching strategy avoids exceeding the rate limit of 5 requests per 30 second period, and the cached data is overwritten when new data is available (daily).
  • I looked at various caching solutions such as NSCache, URLCache, and in-memory caching and persistent caching. NSCache is emptied when the app is terminated / the current session ends, so this doesn't stop the rate limit being exceeded. The caching strategy now uses URLCache which may persist data across app launches, and the data's date is used to determine if a new network request is needed.

Persistence:

  • Persistence of saved quotes is achieved via CoreData.
  • I was looking for an approach which separated CoreData from the rest of the app as much as possible, which ruled out using @FetchRequest in my app's views. For this purpose I wanted to try out Donny Wals' approach of using ObservableObject, the @Published property wrapper and NSFetchedResultsController. You can read his article on it here.
  • The user's appearance setting is persisted by UserDefaults, and the user can change the appearance in the app's settings.
  • If the user sets a new time for notifications that time will be saved to UserDefaults.

Accessibility:

  • There is support for VoiceOver and Dynamic Type.

🚧 Undergoing changes

  • Migrate to Swift 6.
  • Migrate from CoreData to SwiftData.
  • Migrate from ObservableObject to @Observable.
  • Improve testability and test coverage, and add UI tests.
  • Other enhancements and quality of life improvements.

📲 Getting started

  1. Clone the repo.
  2. Open Quotes.xcodeproj.
  3. Build and run.

📱 Screenshots


About

SwiftUI app written in Swift 6 for iOS 27 and iPadOS 27 with Core Data, XCTest and Swift Testing. Accessibility support for Dynamic Type and Voice Over.

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages