Skip to content

Latest commit

 

History

History
168 lines (127 loc) · 4.99 KB

README.md

File metadata and controls

168 lines (127 loc) · 4.99 KB

📱 BPM Workout Visualizer

Sofia Chevrolat (August 2022)

forthebadge forthebadge

A sample app to visualize a workout described by data points in a JSON file on a mapview, along with the heart rate. Supports dynamic type, voice over and dark mode.

Light mode Dark mode

✨ Features

From a JSON file containing workout data points (latitude, longitude, heart rate):

  • Visualize a workout summary - date, title, subtitle and duration of your workout - , along with a plot of your route on a map.

  • The plot is colored according to your heart rate during the workout. A minimalist legend displays the lowest and highest values.

  • Supports:

    • Accessibility Features:
      • Dynamic Type and Bold Text
      • Voice Over (only for the Summary View. A custom rotor would be best for the map view)
    • Dark mode

🔍 Implementation overview

➡️ Overview

  • The sample app follows an MVC architecture
  • The views have been created to be as reusable as possible
  • The WorkoutDataPoint struct conforms to Decodable and implements a custom init(from decoder: Decoder) throws
  • The repository pattern is implemented for retrieving stored data, using:
    • a Repository protocol
    • a generic JSONRepository class that can be used to retrieve any type stored using JSON.

➡️ Programming Concepts and Techniques

  • MVC architecture
  • Repository design pattern
  • Protocols
  • Generics
  • Object Oriented Design (classes, inheritance)
  • Composition
  • Auto Layout with Safe Area
  • Trait Collections
  • Accessibiltiy
  • Dark mode
  • Programmatic UI

➡️ Class Diagram

A full class diagram is provided in the Documentation folder. Below is a shortened version of the most important entities:

classDiagram

%% ============= ENTITIES ============= %%

%% CLASSES

class WorkoutViewController {
    var workout: Workout
    var workoutSummaryView: SummaryView
    var mapView: MKMapView
    var legendView: LegendView

    func plotRoute()
}

class JSONRepository {
    typealias T = StoredType
    ...
}

%% STRUCTS
class Workout { 
    ...
    type: WorkoutType
    ...
    data: [WorkoutDataPoint]
}

class WorkoutDataPoint {
    position: CLLocationCoordinate2D
    heartRate: Int

    init(from decoder: Decoder) throws
}

%% ENUMS
class WorkoutType {
    case running
}

%% PROTOCOL
class Decodable {
    init(from decoder: Decoder) throws
}

class Repository {
    associatedtype T
    ...
}

class MKMapViewDelegate 

%% ========== RELATIONSHIPS ========== %%

WorkoutViewController ..|> MKMapViewDelegate : \nConforms to \n(Conformance)
Workout *-- JSONRepository : \nCreates \n(Composition)
WorkoutViewController "1" *-- "1" Workout : \nCreates \n(Composition)
Workout "1" <.. "1" WorkoutType : \nReceives \n(Dependency)
Workout "1" <.. "1..*" WorkoutDataPoint : \nReceives \n(Dependency)
JSONRepository ..> WorkoutDataPoint : \nFetches
JSONRepository ..|> Repository : \n Conforms to \n(Conformance)
WorkoutDataPoint ..|> Decodable : \n Conforms to \n(Conformance)

Loading

➡️ Testing

The app comes with a few unit tests validating the behavior of the JSONRepository, the key component of the sample app.


📲 Usage

Dependencies and Requirements

The following 2 packages are included:

  • SnapKit for easy view positioning.
  • SwiftFormat for code formatting. Swift format is run at each build and enforces a set of rules declared in the accompanying .swiftformat file.

Steps

  • Open the project in Xcode
  • Run "Resolve Package Versions" (File > Packages) if needed
  • Run the project
    • Try different accessibility font sizes and see the UI update dynamically.
    • Try switching between dark / light mode and see the UI update dynamically.
    • Try using Voice Over to have a human-friendly read of the summary view.
  • Run the tests

📝 Documentation

  • Interface functions and variable are documented with DocC style comments.

These can be used to generate a documentation for the app (as of WWDC2022), that can be hosted on GitHub page or on any other website.