Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Save Health Tracks #11

Open
wants to merge 10 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
language: objective-c
osx_image: xcode9.4
osx_image: xcode10.1

script:
- bundle exec fastlane test
Expand Down
26 changes: 13 additions & 13 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ GEM
remote: https://rubygems.org/
specs:
CFPropertyList (3.0.0)
activesupport (4.2.10)
activesupport (4.2.11)
i18n (~> 0.7)
minitest (~> 5.1)
thread_safe (~> 0.3, >= 0.3.4)
Expand Down Expand Up @@ -36,7 +36,7 @@ GEM
fuzzy_match (~> 2.0.4)
nap (~> 1.0)
cocoapods-deintegrate (1.0.2)
cocoapods-downloader (1.2.1)
cocoapods-downloader (1.2.2)
cocoapods-plugins (1.0.0)
nap
cocoapods-search (1.0.0)
Expand All @@ -49,7 +49,7 @@ GEM
colored2 (3.1.2)
commander-fastlane (4.4.6)
highline (~> 1.7.2)
concurrent-ruby (1.0.5)
concurrent-ruby (1.1.3)
declarative (0.0.10)
declarative-option (0.1.0)
domain_name (0.5.20180417)
Expand All @@ -58,15 +58,15 @@ GEM
emoji_regex (0.1.1)
escape (0.0.4)
excon (0.62.0)
faraday (0.15.3)
faraday (0.15.4)
multipart-post (>= 1.2, < 3)
faraday-cookie_jar (0.0.6)
faraday (>= 0.7.4)
http-cookie (~> 1.0.0)
faraday_middleware (0.12.2)
faraday (>= 0.7.4, < 1.0)
fastimage (2.1.4)
fastlane (2.106.1)
fastimage (2.1.5)
fastlane (2.109.1)
CFPropertyList (>= 2.3, < 4.0.0)
addressable (>= 2.3, < 3.0.0)
babosa (>= 1.0.2, < 2.0.0)
Expand Down Expand Up @@ -114,10 +114,10 @@ GEM
representable (~> 3.0)
retriable (>= 2.0, < 4.0)
signet (~> 0.9)
googleauth (0.6.6)
googleauth (0.6.7)
faraday (~> 0.12)
jwt (>= 1.4, < 3.0)
memoist (~> 0.12)
memoist (~> 0.16)
multi_json (~> 1.11)
os (>= 0.9, < 2.0)
signet (~> 0.7)
Expand All @@ -127,7 +127,7 @@ GEM
httpclient (2.8.3)
i18n (0.9.5)
concurrent-ruby (~> 1.0)
jazzy (0.9.3)
jazzy (0.9.4)
cocoapods (~> 1.0)
mustache (~> 0.99)
open4
Expand Down Expand Up @@ -170,7 +170,7 @@ GEM
rouge (2.0.7)
ruby-macho (1.3.1)
rubyzip (1.2.2)
sass (3.6.0)
sass (3.7.2)
sass-listen (~> 4.0.0)
sass-listen (4.0.0)
rb-fsevent (~> 0.9, >= 0.9.4)
Expand All @@ -192,8 +192,8 @@ GEM
thread_safe (0.3.6)
tty-cursor (0.6.0)
tty-screen (0.6.5)
tty-spinner (0.8.0)
tty-cursor (>= 0.5.0)
tty-spinner (0.9.0)
tty-cursor (~> 0.6.0)
tzinfo (1.2.5)
thread_safe (~> 0.1)
uber (0.1.0)
Expand All @@ -204,7 +204,7 @@ GEM
word_wrap (1.0.0)
xcinvoke (0.3.0)
liferaft (~> 0.0.6)
xcodeproj (1.6.0)
xcodeproj (1.7.0)
CFPropertyList (>= 2.3.3, < 4.0)
atomos (~> 0.1.3)
claide (>= 1.0.2, < 2.0)
Expand Down
77 changes: 62 additions & 15 deletions GeoTrackKit/Core/GeoTrackManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -19,22 +19,34 @@ public class GeoTrackManager: NSObject {
public static let shared: GeoTrackService = GeoTrackManager()

// GeoTrackService stuff
internal var trackingState: GeoTrackState = .notTracking
var trackingState: GeoTrackState = .notTracking
/// Your app's name
internal var appName: String = "No Application Name"
var appName: String = "No Application Name"

// Other stuff
internal var locationManager: CLLocationManager?
var locationManager: CLLocationManager?

/// The last Geo Point to be tracked
fileprivate(set) public var lastPoint: CLLocation?

/// Are we authorized for location tracking?
fileprivate(set) public var authorized: Bool = false

/// The Track
fileprivate(set) public var track: GeoTrack?

/// When we startup, if we find points to be older than this threshold, we toss them away.
/// Defaults to 5 seconds, but you can adjust this as you see fit.
static var oldPointThreshold: TimeInterval = 5
public static var oldPointThreshold: TimeInterval = 5

/// Sets the locationManager instance and then configures it to the needs
/// of GeoTrackKit.
///
/// - Parameter locationManager: The locationManager instance to set.
public func setLocationManager(_ locationManager: CLLocationManager?) {
self.locationManager = locationManager
configureLocationManager()
}
}

// MARK: - API
Expand All @@ -61,6 +73,16 @@ extension GeoTrackManager: GeoTrackService {
return trackingState == .awaitingFix
}

/// Resets the current track
public func reset() {
guard trackingState == .notTracking else {
assertionFailure("reset() cannot be called when tracking")
return GTError(message: "reset() cannot be called when tracking")
}
lastPoint = nil
track = nil
}

/// Attempts to start tracking (if we're not already).
public func startTracking() {
GTInfo(message: "User requested Start Tracking")
Expand All @@ -72,6 +94,7 @@ extension GeoTrackManager: GeoTrackService {
initializeLocationManager()
beginLocationUpdates()
trackingState = .awaitingFix
NotificationCenter.default.post(name: Notification.GeoTrackKit.trackingStarted, object: nil)
}

/// Stops tracking
Expand All @@ -80,6 +103,7 @@ extension GeoTrackManager: GeoTrackService {

endLocationUpdates()
trackingState = .notTracking
NotificationCenter.default.post(name: Notification.GeoTrackKit.trackingStopped, object: nil)
}
}

Expand Down Expand Up @@ -133,7 +157,7 @@ extension GeoTrackManager: CLLocationManagerDelegate {

// Ensure that the first point is recent (not old points which we often get when tracking begins):
if lastPoint == nil {
locations.forEach { (location) in
locations.filter({ $0.isAccurateEnough }).forEach { location in
guard abs(location.timestamp.timeIntervalSinceNow) < GeoTrackManager.oldPointThreshold else {
return
}
Expand All @@ -143,7 +167,7 @@ extension GeoTrackManager: CLLocationManagerDelegate {
return
}
} else {
recentLocations = locations
recentLocations = locations.filter { $0.isAccurateEnough }
}

GTDebug(message: "New Locations: \(recentLocations)")
Expand All @@ -158,7 +182,7 @@ extension GeoTrackManager: CLLocationManagerDelegate {
return
}
track.add(locations: recentLocations)
NotificationCenter.default.post(name: Notification.Name.GeoTrackKit.didUpdateLocations, object: recentLocations)
NotificationCenter.default.post(name: Notification.GeoTrackKit.didUpdateLocations, object: recentLocations)
}

/// Handles location tracking pauses
Expand All @@ -167,7 +191,7 @@ extension GeoTrackManager: CLLocationManagerDelegate {
public func locationManagerDidPauseLocationUpdates(_ manager: CLLocationManager) {
GTDebug(message: "Paused Location Updates")
track?.pauseTracking(message: "locationManagerDidPauseLocationUpdates event")
NotificationCenter.default.post(name: Notification.Name.GeoTrackKit.didPauseLocationUpdates, object: nil)
NotificationCenter.default.post(name: Notification.GeoTrackKit.didPauseLocationUpdates, object: nil)
}

/// Handles location tracking resuming.
Expand All @@ -176,7 +200,7 @@ extension GeoTrackManager: CLLocationManagerDelegate {
public func locationManagerDidResumeLocationUpdates(_ manager: CLLocationManager) {
GTDebug(message: "Resumed Location Updates")
track?.startTracking(message: "locationManagerDidResumeLocationUpdates event")
NotificationCenter.default.post(name: Notification.Name.GeoTrackKit.didResumeLocationUpdates, object: nil)
NotificationCenter.default.post(name: Notification.GeoTrackKit.didResumeLocationUpdates, object: nil)
}

/// Handles location tracking errors
Expand All @@ -187,7 +211,7 @@ extension GeoTrackManager: CLLocationManagerDelegate {
public func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
GTError(message: "Failed to perform location tracking: \(error.localizedDescription), \(error)")
track?.error(error: error)
NotificationCenter.default.post(name: Notification.Name.GeoTrackKit.didFailWithError, object: error)
NotificationCenter.default.post(name: Notification.GeoTrackKit.didFailWithError, object: error)
}

/// Handles deferred update errors.
Expand All @@ -205,14 +229,14 @@ extension GeoTrackManager: CLLocationManagerDelegate {
} else {
track?.error(message: "locationManager:didFinishDeferredUpdatesWithError: nil error")
}
NotificationCenter.default.post(name: Notification.Name.GeoTrackKit.didFinishDeferredUpdatesWithError, object: error)
NotificationCenter.default.post(name: Notification.GeoTrackKit.didFinishDeferredUpdatesWithError, object: error)
}

}

// MARK: - Helpers

fileprivate extension GeoTrackManager {
private extension GeoTrackManager {

/// Initializes the location manager and sets the preferences
func initializeLocationManager() {
Expand All @@ -221,6 +245,14 @@ fileprivate extension GeoTrackManager {
}

let locationManager = CLLocationManager()
setLocationManager(locationManager)
}

/// Configures the locationManager
func configureLocationManager() {
guard let locationManager = locationManager else {
return
}
locationManager.activityType = .fitness
locationManager.desiredAccuracy = kCLLocationAccuracyBest

Expand All @@ -231,8 +263,6 @@ fileprivate extension GeoTrackManager {
locationManager.distanceFilter = 10
locationManager.allowsBackgroundLocationUpdates = true
locationManager.delegate = self

self.locationManager = locationManager
}

/// Handles requesting always authorization from location services
Expand Down Expand Up @@ -265,12 +295,29 @@ fileprivate extension GeoTrackManager {

}

// MARK: - CLLocation

extension CLLocation {

/// Is the accuracy of the point within the acceptable range?
var isAccurateEnough: Bool {
return horizontalAccuracy <= 50
}
}

// MARK: - Notifications

public extension Notification.Name {
public extension Notification {

/// GeoTrackKit notification constants
public struct GeoTrackKit {

/// Notification that the user has started tracking
public static let trackingStarted = Notification.Name(rawValue: "com.geotrackkit.user.started.tracking")

/// Notification that the user has stopped tracking
public static let trackingStopped = Notification.Name(rawValue: "com.geotrackkit.user.stopped.tracking")

/// Notofication that the location was updated
public static let didUpdateLocations = Notification.Name(rawValue: "com.geotrackkit.did.update.locations")

Expand Down
3 changes: 3 additions & 0 deletions GeoTrackKit/Core/GeoTrackService.swift
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ public protocol GeoTrackService {
/// The most recently tracked point
var lastPoint: CLLocation? { get }

/// Resets the current track
func reset()

/// Starts tracking
func startTracking()

Expand Down
30 changes: 30 additions & 0 deletions GeoTrackKit/Core/Map/UIModels/UIGeoTrack.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
// Copyright © 2017 Eric Internicola. All rights reserved.
//

import CoreLocation
import Foundation

/// A UI Model for a track. It keeps track of a Track (`GeoTrack`), a Track Analyzer (`GeoTrackAnalyzer`) and a collection of Legs (ascents, descents) that are currently visible
Expand Down Expand Up @@ -86,6 +87,35 @@ public extension UIGeoTrack {
return analyzer.legs
}

/// Gets you an array of points for the provided leg
///
/// - Parameter index: The index of the leg you want to get the points for.
/// - Returns: An array of CLLocation objects which are the points for the leg.
func getPoints(forLeg index: Int) -> [CLLocation]? {
guard index < allLegs.count else {
return nil
}
let leg = allLegs[index]
return getPoints(for: leg)
}

/// Gets you an array of points for the provided leg
///
/// - Parameter leg: The leg that you want the points for.
/// - Returns: An array of CLLocation objects which are teh points for the leg.
func getPoints(for leg: Leg) -> [CLLocation]? {
let range = leg.index...leg.endIndex

return Array(track.points[range])
}

var startDate: Date? {
return track.points.first?.timestamp
}

var endDate: Date? {
return track.points.last?.timestamp
}
}

// MARK: - Helpers
Expand Down
Loading