Sample iOS application for showing specific articles downloaded from the internet.
The project can be built using Xcode 11.1 and supposed to be running on iOS 11 or later.
The application can be used both on iPhone and iPad.
Master-detail approach is used leveraging split view controller to maximize the usage of available space on the screen.
AppCoordinator sets up a relationship between view controllers and organizes their presentations. View controllers do not present other view controllers (see the coordinator pattern for details), but have closures used by the coordinator to set up presentation logic. The only exception is presenting error alert, which is done from the view controller itself (see FeedViewController.loadData()). Its another responsibility is a propagation of data provider used by view controllers.
Getting info is abstracted by the data provider hiding behind the FeedDataProviding protocol. Its concrete implementation (FeedDataProvider) uses the test endpoint. Usage of this approach allows to mock data provider for development purposes as well as simulate various errors. FeedDataProvider uses the HTTPClient abstraction to obtain data from the network (as well as handle network errors).
Async data loading and cancellation is based on rocks of futures and Swift 5 Result type. Future implementation is inspired by the mentioned article. The Combine could be used instead as of iOS 13, but since min spec is iOS 11, the custom solution is to be implemented.
The list of articles (feed) is presented in table view managed by the FeedViewController class inherited from generic TableViewController. TableViewController allows not only to manage and present teasers, but also show activity indicator when loading, and error page on error as well as reload data. FeedViewController is supposed to be presented in navigation controller.
Pull to refresh is used to update the feed.
Articles are presented in text view managed by ArticleViewController. It aslo shows a special label when there is no selection in the table view (applicable for iPad and plus iPhones). Text Kit is used for laying out images along with text data, and for that special text attachment containing UIView instance is used (see TextAttachment and ImageTextAttachment).
Images are retrieved asynchronously using the HTTPClient entity too and this process is abstracted by the ImageFetching protocol. The concrete implementation of that protocol (ImageFetcher) uses both in-memory and disk caches, which in turn allows to avoid their re-fetching from the network once fetched.
Special techniques are used to support dynamic type as an important accessibility future.
Since standard UIKit controls are used, accessibility should not be an issue, but for sure requires auditing.
Ready for localisation by using NSLocalizedString.
Swift coding style is checked by SwiftLint if it's installed.
- Self sizing of table view cells containing attributed strings is slow by design: especially because attributed strings are created every time, and measurements are not cached, but even performed twice: when size if determined (
sizeThatFits) and when layout is performed (layoutSubviews). This can be improved by caching attributed strings and results of measurements for various widths (for instance, inNSCachenot to exceed memory limits). - Offline support: the application is useless when there is no connection. Its support can be added by using CoreData or some persistent store like YapDatabase or FMDB. When cached data is provided, a corresponding network request is performed and newly obtained data is merged with existing cached one causing update or the UI. NSFetchedResultsController or similar entity may be used to update UI in animated fashion.
- Test harness has to be extended for UI code, in particular view controllers. Snapshot tests can be used to make sure there are no regressions.
- Tracking availability of network connection: it makes sense to reinitiate failed updates upon getting connected.
- Error handling requires improving; logging can be collected by using for instance XCGLogger
- Disk caches for images is not purged by the app, allowing it to grow until iOS starts experiencing the disk space pressure and starts removing local app caches
- Application icon and branding is missing, i.e. specific tint colours and assets
- Not 100% ready for internationalisation: in particular, layout has to be adjusted for RTL
- Full screen mode for showing images with zooming support
- Moving build settings to configuration files is always a nice thing to do
- Minor layout issues can be observed when rotating device