SwiftPokedex is a simple Pokedex app written by Viktor GidlΓΆf in Swift that implements the PokeAPI. For full documentation and implementation of PokeAPI have a look at the their documentation.

This app demonstrates:

  • RIB architecture πŸ›
  • Network capabilities using Combine ⚑️
  • Data driven table and collection views πŸ’Ύ
  • Async image download and caching 🏞
  • Swift dot syntax ✏️
  • Custom navigation bar 🧭
  • Custom fonts πŸ“–
  • Infinite scrolling πŸ“œ

It downloads an array of Pokemon and displays them in a grid. The most dominant color of the Pokemon sprite is detected and shown in the UI. It also shows a list of the most common items.


Architecture πŸ›

SwiftPokedex is written in my own interpretation of the RIB archtitecure created by Uber. The name RIBs is short for Router, Interactor and Builder, which are core components of the architecture.

Builder πŸ› 

The builder builds the views with all of their dependencies.

final class PokedexViewBuilder {
    static func build() -> NavigationController {
        let router = PokedexRouter()
        let interactor = PokedexInteractor(router: router)
        let viewController = PokedexViewController(interactor: interactor)
        let navigationController = NavigationController(rootViewController: viewController)
        router.navigationController = navigationController
        return navigationController

Interactor πŸ‘‡πŸ»

The interactor is the link between the user input and the view and includes all the interations the user can make. It also contains a router object. So when the user interacts with the view we call the interactor to make the appropriate interaction.

override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
    collectionView.deselectItem(at: indexPath, animated: true)

    interactor.selectPokemon(at: indexPath, in: collectionView)

Router πŸ•Ή

The router is in charge of navigation. And since routers are decoupled from view controllers we can easily navigate to anywhere in the app.

func routeToDetailView(pokemon: PokemonDetails, color: UIColor) {
    let detailView = DetailViewBuilder.build(from: pokemon, withColor: color)
    navigationController?.pushViewController(detailView, animated: true)

Networking ⚑️

SwiftPokedex uses Combine for all the API calls to the PokeAPI. This structure can exceute any request over the network.
The PokemonAPI and ItemAPI is then build around this network agent.

struct NetworkAgent {
    static func execute<T: Decodable>(_ request: URLRequest, logJSON: Bool = false) -> AnyPublisher<T, Error> {
        URLSession.shared.dataTaskPublisher(for: request)
            .tryMap {
                if logJSON { print($0.data.prettyJSON ?? "no json") }
                return $0.data
            .decode(type: T.self, decoder: JSONDecoder())

Data driven tables and collection views πŸ’Ύ

The table views and collection views are data driven and they setup their own UI based on the data they are given. So setting up a collection view data source is done like this:

let items = pokemon.map { CollectionCellConfiguration<PokedexCell, PokemonDetails>(data: $0) }
let section = UICollectionView.Section(items: items)
let collectionData = UICollectionView.DataSource(sections: [section])

By using CollectionCellConfiguration we can configure cells for the collection view with any data type. Here we specify that the data is PokemonDetails and the cell type is PokedexCell. This way it is type safe to set up cells. Then the collection view automatically renders that data with those cells. No need to implement any of the collection delegate or data source methods in the view controller. That is done by the CollectionCellConfigurator protocol and a subclass of UICollectionViewController.

Todo πŸ“

The PokeAPI is very extensive and it contains a lot of things. Here are some things that I plan to implement further down the line:

  • [x] Request pokemon
  • [ ] Search pokemon
  • [x] Pokedex pagination
  • [x] Show pokemon details
  • [x] Request items
  • [x] Search items
  • [x] Show item descriptions
  • [ ] Implement other parts of the API such as:
    • Moves
    • Abilities
    • Berries

Requirements ❗️

  • Xcode 12.0+
  • iOS 14.1+
  • Swift 5+