https://github.com/vladimir-kaltyrin/exchanger
Example of implementing VIPER 💎 and Clean Architecture 💍 in Objective-C
https://github.com/vladimir-kaltyrin/exchanger
abstract-factory-pattern clean-architecture coredata currency-exchange-rates exchange-rates objc objective-c soa unit-testing viper viper-architecture viper-modules viper-pattern-architecture
Last synced: 14 days ago
JSON representation
Example of implementing VIPER 💎 and Clean Architecture 💍 in Objective-C
- Host: GitHub
- URL: https://github.com/vladimir-kaltyrin/exchanger
- Owner: vladimir-kaltyrin
- License: mit
- Created: 2017-07-10T09:30:34.000Z (almost 8 years ago)
- Default Branch: master
- Last Pushed: 2017-12-21T16:25:54.000Z (over 7 years ago)
- Last Synced: 2024-11-17T04:35:45.143Z (6 months ago)
- Topics: abstract-factory-pattern, clean-architecture, coredata, currency-exchange-rates, exchange-rates, objc, objective-c, soa, unit-testing, viper, viper-architecture, viper-modules, viper-pattern-architecture
- Language: Objective-C
- Homepage:
- Size: 11.8 MB
- Stars: 13
- Watchers: 2
- Forks: 6
- Open Issues: 0
-
Metadata Files:
- Readme: readme.md
- License: LICENSE
Awesome Lists containing this project
- fucking-open-source-ios-apps - Exchanger
README
[](https://www.bitrise.io/app/db9b8a614ca81158)

# Exchanger
The Exchanger is a simple iOS application demonstrating one of approaches to implement VIPER 💎 architecture in modern Objective-C.
# Table of contents
* [About](#about)
* [Setup](#setup)
* [CocoaPods](#cocoapods)
* [OCLint](#oclint)
* [XCPretty](#xcpretty)
* [Notes on implementation](#notes)
* [Architecture](#architecture)
* [VIPER](#viper)
* [Type Inference](#typeinference)
* [Blocks](#blocks)
* [CarouselView](#carouselview)
* [Persistance](#persistance)
* [Tests](#tests)## About
The application is a fairly straightforward currency converter. It takes a reference rate from a European Central Bank by parsing its [public XML](http://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml) and provides a feature to exchange any currency including EUR, USD and GBP in any combination. The exchange rate is automatically updated each 30 seconds.
When app starts there is a limited balance with 100 units of each currency.
There are two text inputs on the screen, both are cyclic carousel views for choosing currency to exchange.YouTube video of how it works:
The app core is carefully designed with love ❤️ to SOLID in pure Objective-C using VIPER architecture combined with SOA. Meanwhile, unit tests are written in Swift.
If you have any questions just [email me](mailto:[email protected]). Feel free to open issues 😀
## Setup
### CocoaPods
To install all project dependencies just use CocoaPods:
```bash
pod install
```### OCLint
If OCLint is not installed on your machine then run following commands in Terminal:
```bash
brew tap oclint/formulae
brew install oclint
```### XCPretty
If XCPretty is not installed on your machine then run following commands in Terminal:
```bash
gem install xcpretty
```## Notes on implementation
### Architecture
The app is intended to implement the clean architecture.

### VIPER
Each screen is represented as VIPER module. In this implementation of VIPER there is a Router
class for navigation between screens and functional callbacks to interact with module, for example:```objective-c
@protocol ExchangeMoneyModule
@property (nonatomic, strong) void(^onFinish)();- (void)dismissModule;
@end
```
### Type Inference
Type Inference is a common feature in Swift, but Objective-C by default doesn't provide it. It's easy to avoid this
issue by using C macroses, as it's provided below:```objective-c
#define let __auto_type const
#define var __auto_type
```Without using __auto_type:
```objective-c
NSArray *currencies = data.currencies;
```With using using __auto_type:
```objective-c
let currencies = data.currencies;
```### Blocks
There is a common pattern in Objective-C to call a block:
```objective-c
if (block != nil) {
block();
}
```With optionals and closures syntax introduced in Swift this syntax looks especially overweighted.
There is a C macros to deal with that:```objective-c
#define safeBlock(block, ...) if (block != nil) { block(__VA_ARGS__); }
```### CarouselView
CarouselView implementation uses dummy UITextField in order to keep some first responder on the screen.
It that way the keyboard is always on the screen which is a nice UX.### Persistance
App saves the state using simple Core Data storage.
### Tests
Unit tests are provided for service layer and core layer including formatters. Some folks prefer to write unit tests for Presenter and Interactor. In practice it may be a case of accidental complexity. When business logic is located mainly in services, then unit tests for service layer are appropriate. Interactor just passes values from presenter to services. Presenter's code is often changing and it makes more sense to write UI tests. In this way unit tests for Interactor and Presenter are recommended but there is no strict need to write tests for them meanwhile code keeps to be testable and maintable.