An app made with ❤️ to demonstrate some examples of clean architecture, code organisation, loose coupling, unit testing and some of the best practices used in modern iOS programming using Swift
.
App Goal:
- Load a list of facts (could be anyhting, E.g. for a Country like Canada)
- Show those facts in table view
- Download images of those facts asynchronously as if needed to be displayed (prefetching as desired)
- Add suport for iPhone and iPad in all orientation and size classes to adapt the UI nicley
- Apply some custom styling and theming
- Add support for iOS 13 Dark mode (if iOS 13 only, uses default light mode for iOS 11 and 12)
A simple list of facts are saved in a dropbox location that serves as a GET api call for JSON api response.
https://dl.dropboxusercontent.com/s/2iodh4vg0eortkl/facts.json
- Xcode 11.4(required) with Swift 5.0
- For convenience
Carthage/Checkouts
andCarthage/Build
folders are checked in the repo. So if you are downloading/cloning this project, those areready
andXcode 11.4
should compile as long asSwift 5.0
is available. - Optional step: Run the Carthage (version 0.32 or later) update command to
fresh install
the dependent libraries in theCartfile
carthage update --platform iOS
- Clean and build the project in Xcode or
/DerivedData
folder if needed
RxSwift
- to makeReactive
binding of API calls and responses 😇SnapKit
- to snap auto layout constraints with ease 🤓SkeletonView
- to show loading shimmers... 🙈Quick
- to unit test as much as possible 👨🏽🔬🧪Nimble
- to pair with Quick for easy syntaxing 👬
- VIPER & MVP - A hybrid achitecture
- Clean communication between
Display
,Presenter
in the view/scene stack - Communication between
Interactor
,Service
in the lower stacks of domain & network layers - Connectivity of this components are achieved via protocol instances to achieve loose coupling and unit testability
View
(i.e. View Controller) isDisplay
itself and contacts itsPresenter
Presenter
may perform view related logic and immediately talk back toDisplay
(e.g. list data source handling, image lading operation queues)Presenter
can communicate with underlyingInteractor
layer for more complex taskInteractor
decides all Domain level business logic to take care ofInteractor
communicates with underlyingService
layerService
communicates to its underlyingHttpClient
which handles all networkingInteractor
gets back information viaRx
binding fromService
Interactor
parses the data and apply any necessary data transformation (eg. empty list of facts or subject name missing etc.)Interactor
gives outcome back toPresenter
via callbacksPresenter
handles all the presentation reated logic nesessary for the viewPresenter
uses a helperTransformer
that only cares about domain data to presentation item transformation needed for table cell UI bindingPresenter
talks back toDisplay
and commands UI update tasksPresenter
talks back toRouter
(if available and needed) for navigation tasks
Folder / Grouping are done as per below:
Project has 3 targets:
- MyCountry - The main code
- MyCountryTests - Unit testing of all the code layers using Quick/Nimble
- MyCountryUITests - No tests implemented yet. Can be done via Mocking API response via library like
Embassy
The codebase is grouped into 3 layers -
PresentationLayer
,DomainLayer
, &NetworkLayer
It has all the presnetation logic
- Has helpers such as Theme, Localization, Accessbility etc.
- Has one main scene:
FactsList
: The list of facts in table view
Breakdown of each
Scene
stack:
ViewController
Presenter
Display
Router
(optional if needed) Presenter & Display communication logics are unit tested. If there exists aRouter
, that can be unit tested too. In this app, it's single view app, hence noRouter
is used.
It has all domain level logic via the Interactor
FactsInteractor
which loads the facts- Data model used -
FactsList -> (subjectName, [Fact])
- The logic is unit tested
It has all data/network layer logic
BaseRequest
->FactsFindingRequest
&ImageLoadingRequest
FactsFindingService
&ImageLoadingService
HTTPClient
uses Apple'sURLSession
ObservableDataSource
is used to provide a layer of abstraction and to be able to unit testDecodable
Data model used forFact
andFactsList
- Above logics are unit tested
- Same layout in both potrait and landscape mode
- Compact (i.e. narrow) layout in potrait mode
- Regular (i.e. wide) layout in landscape mode
- Regular (i.e. wide) layout in both potrait and landscape mode
Error Handling
Network connection unavailable
error is shown separately- Any other error leads into a
generic
error message