Git Product home page Git Product logo

swiftgoal's Introduction

SwiftGoal

This project showcases the Model-View-ViewModel (MVVM) architecture with ReactiveCocoa 4, while serving as a digital logbook of FIFA matches. It was inspired on a theoretical level by Justin Spahr-Summers' talk Enemy of the State, and on a more practical one by Ash Furrow's C-41 app.

As the Swift language and the ecosystem around it matured, porting the original ObjectiveGoal project became a natural next step, as Swift's type safety makes it a perfect fit for functional reactive programming.

Requirements

SwiftGoal runs on iOS 9+ and requires Xcode 7.3 with Swift 2.2 to build.

Setup

No separate backend is required to use the app, as it stores all its data locally in the Documents directory by default. Note that things might break in future releases, e.g. if some model fields change! Also, you need to terminate the app to trigger a write to local storage.

For serious use and if you want to share data across multiple devices, I recommend you use Goalbase as a backend. It's easy to get started:

  1. Follow the setup instructions in the Goalbase documentation.
  2. Enable the "Use Remote Store" switch under Settings > SwiftGoal.
  3. Make sure the base URL is set correctly. The default value should be fine if you run rails server in your Goalbase directory, but for a remote setup (e.g. on Heroku) you'll need to update this setting.

Unit Tests

SwiftGoal is thoroughly covered by unit tests, which are written with Quick and Nimble. An advantage of such BDD-style frameworks is that they document the behavior of the tested code in plain English. To run the unit tests, simply hit Cmd + U in Xcode.

User Features

  • Create players
  • Create matches with home/away players and score
  • View list of matches
  • Edit existing match information
  • Delete matches
  • Pull-to-refresh any list in the app
  • See animated list changes
  • Enjoy custom fonts and colors
  • Get alerts about network and server errors
  • View player rankings
  • Switch between different ranking periods (last month, all time, …)
  • See date and time of each match
  • See matches grouped by date range (e.g. last week, last month, earlier)
  • View more player statistics (e.g. won/drawn/lost count, nemesis player, …)

Code Checklist

  • Validate player name before creating
  • Validate match player counts before creating
  • Move base URL to Settings for easy customization
  • Cancel network requests when the associated view becomes inactive
  • Retry network requests 1 or 2 times before giving up
  • Detect and animate match data changes
  • Write tests for models
  • Write tests for view models
  • Write tests for helpers and store
  • Deduplicate isActiveSignal code on view controllers (via a class extension)
  • Create watchOS 2 app for quick match entry

Benefits of MVVM

High testability: The basic premise of testing is to verify correct output for a given input. As a consequence, any class that minimizes the amount of dependencies affecting its output becomes a good candidate for testing. MVVM's separation of logic (the view model layer) from presentation (the view layer) means that the view model can be tested with minimal setup. For instance, injecting a mock Store that provides a known amount of Match instances is enough to verify that the MatchesViewModel reports the correct amount of matches. The view layer becomes trivial, as it simply binds to those outputs.

Better separation of concerns: UIViewController and its friends have been rightfully scorned for handling far too many things, from interface rotation to networking to providing table data. MVVM solves this by making a clear cut between UI and business logic. While a view controller would still acts as its table view's data source, it forwards the actual data queries to its own view model. Presentation details, such as animating new rows into the table view, will be handled in the view layer.

Encapsulation of state: As suggested by Gary Bernhardt in his famous talk “Boundaries”, view models offer a stateful shell around the stateless core of the app, the model layer. If need be, the app's state can be persisted and restored simply by storing the view model. While the view may be extremely stateful too, its state is ultimately derived from that of the view model, and thus does not require to be stored.

Acknowledgements

This project is kindly sponsored by Futurice as part of their fantastic open-source program. Kiitos!

The icons within the app are courtesy of Icons8 – a resource well worth checking out.

swiftgoal's People

Contributors

richeterre avatar

Watchers

James Cloos avatar  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.