This project is a sample of my own iOS architecture (VIPER + Rx + Moya). I used Instagram API. You will find the test account down below. If you want to improve it or there are some mistakes, please feel free to tell me. Any advice is welcome.
- Swift 3
- iOS 9.0+
With the VIPER architecture, we need to init all pieces of blocks before calling the ViewController. That is the reason why, everything is done in the router. That means, if you need to call a ViewController, you have to call the router.
Here is an example :
// in my HomeRouter.swift
var homeViewController : HomeViewController?
func getInitViewController() -> HomeViewController? {
let storyboard = UIStoryboard(name: "Main", bundle: nil)
self.homeViewController = storyboard.instantiateViewController(withIdentifier: "HomeViewController") as? HomeViewController
self.initViper()
return self.homeViewController
}
fileprivate func initViper() {
let presenter = HomePresenter()
let getMediaRecentInteractor = GetMediaRecentInteractor()
presenter.router = self
presenter.viewDelegate = self.homeViewController
presenter.getMediaRecentInteractor = getMediaRecentInteractor
self.homeViewController?.presenter = presenter
}
And later :
// if you want to go to the Home, do it in your Router
if let homeViewController = HomeRouter().getInitViewController() {
self.currentViewController?.present(homeViewController, animated: true, completion: nil)
}
In this architecture, I used VIPER and RX. Therefore, each Interactor will create an observable and the Presenter will be the observer. This will avoid multiple callbacks/delegates.
Here is an example :
// GetMediaRecentInteractor.swift
func getMediaRecent() -> Observable<MediaRecentResponseEntity> {
let provider = RxMoyaProvider<InstagramService>()
return provider.request(InstagramService.mediaRecent).mapObject(MediaRecentResponseEntity.self)
}
In the Presenter :
func getMediaRecent() {
self.getMediaRecentInteractor?.getMediaRecent()
.observeOn(MainScheduler.asyncInstance)
.subscribe(onNext: { (mediaRecentResponseEntity) in
// update view
}, onError: { (error) in
// display error
}, onCompleted: {
// do something onCompleted
}).addDisposableTo(self.disposeBag)
}
- login: jeromechatest
- password : jeromechatest1234
- Get recents media
- Get user profile datas
- 3d touch to preview pictures
- This project doesn't handle instagram video yet
- In this project I used a GlobalRouter to avoid duplicated codes to managed redirects
- I used a GlobalViewController too in order to manage a custom navigation bar