Code Monkey home page Code Monkey logo

getupside-challenge's Introduction

GetUpside-Challenge

Description:

GetUpside-Challenge is a 2-screen POC to explore Clean Swift Architecture + Coordinator, in conjunction with the State Machine and DI Container pattern.

In scope of POC following user story has been implemented:

Implement an iOS application using Swift, which will show nearby food places as pins on the Google Maps. List of all found places also should be available for display.

Technical requirements:

  • ✔️ You should use ArcGIS Runtime SDK for iOS as a service that provides places;
  • ✔️ Limit a number of places fetched to 20. You should store them (last 20 fetched places) locally using Realm;
  • ✔️ on app start, initial map camera position has to be centered to device location with zoom level 14.
  • ✔️ If there are stored places on app start, that are visible on initial screen, show them and don't make a service fetch call;
  • ✔️ fetching places should happen only when all map interactions stopped (zoom, pan or camera movement). All fetched places have to be visible on map after search;
  • ✔️ completed test assignment should be uploaded to GitHub and only link to it provided as a final solution. Project needs to have instructions for launching the app in Xcode;

In additional:

  • ✔️ Splash screen;
  • ✔️ Clustering;
  • ✔️ Filtering by category and by near user location (20 km);
  • ✔️ Visualizing touch on screen;

Demo

Given below a demo of some features which have been implemented in scope of project experience.

How to compile and run project:

  • Since app used 3rd part frameworks, distributed via cocoapods. Install cocoapods in regular way:
    • Change the working directory (currently GetUpside-Challenge);
    • Then, run the following command:
      $ pod install
      
  • Open GetUpside-Challenge.workspace;
  • Build and run the app;

Structure of project:

The project contains separated modules/frameworks + application (listed below):

  • GetUpside-Challenge - iOS target which implements technical requirements together with additional featues provided (architectual approch described bellow).
  • FutureKit - framework which provides an API for performing non-blocking asynchronous requests and combinator interfaces for serializing the processing of requests, error recovery and filtering. In most iOS libraries asynchronous interfaces are supported through either delegate-protocol pattern or with a callback. Even simple implementations of these interfaces can lead to business logic distributed over many files or deeply nested callbacks that can be hard to follow. FutureKit provides a very simple API to get rid of callback hell (inspired by www.swiftbysundell.com).

FutureKit is analog Future/Promise, provided by Combine with advantage that the framework is available in iOS 10+, whereas Future/Promises available starting with iOS 13.

  • ReusableKit - framework which contains generic routines to reuse UIKit/Cocoa elements. Currently supports UITableView and UICollectionView.
  • UI - framework which provided some featured UI elements (Probably, some components are going to be taken out into separated distributed pakage to reuse in other project experiences).
  • FilterKit - framework contains unified routines for filtering elements.

The frameworks have been put into a separates modules so that they can be reused in other projects (if necessary, they are assembled into a static/dynamic frameworks).

Also GetUpside-Challenge is using 3rd party frameworks including ArcGIS Runtime SDK for iOS, and GoogleMaps.

Architectural approach:

As it's been mentioned GetUpside-Challenge is following Clean Architecture pattern (VIP) (by Robert C. Martin (Uncle Bob)).

Entire project classes might be devided into 3 layers: Data, Domain, and Presentation layers. Data layer components:

Domain layer components:

Presenation layer components:

From the bottom direction:

Each service works with its own data entity. The worker stores a reference to a service instance and handles all requests and API responses to that data service. It implements its own specific "use case", such as specific business scenarios. It also converts data from data entities to domain entities using converters/translators (another "pros" of this approach, the data entity can only be used in the thread/sequence where it was created, as it does in Realm, and by converting to a domain-layer entity, the user removes the restriction on use in a particular thread). Interactor observes callbacks from workers and, depending on the data received, changes states in the State Machine accordingly (used to handle complex scenarios). Presenter subscribes to state changes and prepares data for display by packaging it into ViewModel instances and notifying the view (scene) coherently. Each screen "knows" how to display its particular ViewModel. Within a single scene, there is one interactor - the presenter. The Interceptor-Presenter-View relationship is referred to in various sources as the VIP cycle.

From the opposite direction:

The screens call the interactor, forming a request, and the interactor runs the specific scenario described.

Described above might be visualized with following graph.

In addition, the application uses a Coordinator pattern. It is used to handle various navigation threads. The interactor keeps the coordinator as a delegate and notifies it through events. Coordinator contains a reference to the Dependency Injection Container (DI Container). It essentially stores references to global application services (such as URLSession, LocationManager, Realm etc.), and DI "knows" the scene instantiation rules. These "rules" also instantiate interactors and pass them to the scene initializer as parameter (Initializer injection). Thus, each instance can be easily mocked/stubbed during unit testing.

Supporting platforms:

  • iOS 12.0+;

getupside-challenge's People

Contributors

romanvovkgl avatar roman-vovk avatar vovkroman avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.