mirror of
https://github.com/eclipse-sailing-analytics/sailing-analytics.git
synced 2026-10-27 22:37:15 +00:00
More needed refactoring steps
This commit is contained in:
1 parent
376bcc2d34
commit
cd860fcc08
29 files changed
+805
-552
No files matched your search
@@ -9,7 +9,7 @@
|
||||
/* Begin PBXBuildFile section */
|
||||
066B0DF652B5D2B188D4884B /* libPods-SAPTracker.a in Frameworks */ = {isa = PBXBuildFile; fileRef = B1229BB88872CD20C0AE25DE /* libPods-SAPTracker.a */; };
|
||||
7F0658FD19F7D6700077FF95 /* ScanViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7F0658FC19F7D6700077FF95 /* ScanViewController.swift */; };
|
||||
7F0658FF19F7EE910077FF95 /* CheckInData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7F0658FE19F7EE910077FF95 /* CheckInData.swift */; };
|
||||
7F0658FF19F7EE910077FF95 /* RegattaData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7F0658FE19F7EE910077FF95 /* RegattaData.swift */; };
|
||||
7F14A10A1A13B9A6001C1ECB /* _abkhazia.png in Resources */ = {isa = PBXBuildFile; fileRef = 7F14A0041A13B9A6001C1ECB /* _abkhazia.png */; };
|
||||
7F14A10B1A13B9A6001C1ECB /* _basque-country.png in Resources */ = {isa = PBXBuildFile; fileRef = 7F14A0051A13B9A6001C1ECB /* _basque-country.png */; };
|
||||
7F14A10C1A13B9A6001C1ECB /* _british-antarctic-territory.png in Resources */ = {isa = PBXBuildFile; fileRef = 7F14A0061A13B9A6001C1ECB /* _british-antarctic-territory.png */; };
|
||||
@@ -311,7 +311,6 @@
|
||||
C852BAA21CF5E1EA0093B0C5 /* RequestManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = C852BAA11CF5E1EA0093B0C5 /* RequestManager.swift */; };
|
||||
C852BAAB1CF736680093B0C5 /* Preferences.swift in Sources */ = {isa = PBXBuildFile; fileRef = C852BAAA1CF736680093B0C5 /* Preferences.swift */; };
|
||||
C8603D511C52892A002B2F28 /* Acknowledgements.markdown in Resources */ = {isa = PBXBuildFile; fileRef = C8603D491C528832002B2F28 /* Acknowledgements.markdown */; };
|
||||
C8739D8E1D23D53C00A89F3C /* SendGPSFixesController.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8739D8D1D23D53C00A89F3C /* SendGPSFixesController.swift */; };
|
||||
C8739E041D2AA2A500A89F3C /* Regatta+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8739DFA1D2AA2A500A89F3C /* Regatta+CoreDataProperties.swift */; };
|
||||
C8739E051D2AA2A500A89F3C /* Regatta.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8739DFB1D2AA2A500A89F3C /* Regatta.swift */; };
|
||||
C8739E061D2AA2A500A89F3C /* GPSFix+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8739DFC1D2AA2A500A89F3C /* GPSFix+CoreDataProperties.swift */; };
|
||||
@@ -322,6 +321,12 @@
|
||||
C8739E0B1D2AA2A500A89F3C /* Competitor.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8739E011D2AA2A500A89F3C /* Competitor.swift */; };
|
||||
C8739E0C1D2AA2A500A89F3C /* Event+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8739E021D2AA2A500A89F3C /* Event+CoreDataProperties.swift */; };
|
||||
C8739E0D1D2AA2A500A89F3C /* Event.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8739E031D2AA2A500A89F3C /* Event.swift */; };
|
||||
C8739E0F1D2BEE7900A89F3C /* RegattaController.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8739E0E1D2BEE7900A89F3C /* RegattaController.swift */; };
|
||||
C8739E121D2BF14F00A89F3C /* EventData.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8739E111D2BF14F00A89F3C /* EventData.swift */; };
|
||||
C8739E141D2BF16300A89F3C /* LeaderboardData.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8739E131D2BF16300A89F3C /* LeaderboardData.swift */; };
|
||||
C8739E161D2BF17900A89F3C /* CompetitorData.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8739E151D2BF17900A89F3C /* CompetitorData.swift */; };
|
||||
C8739E181D2BF2DC00A89F3C /* BaseData.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8739E171D2BF2DC00A89F3C /* BaseData.swift */; };
|
||||
C8739E1C1D2D5F1700A89F3C /* LocationData.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8739E1B1D2D5F1700A89F3C /* LocationData.swift */; };
|
||||
C89C5FC51D06A289002AAAD2 /* GradientView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C89C5FC41D06A289002AAAD2 /* GradientView.swift */; };
|
||||
C89C5FCA1D06CECD002AAAD2 /* StatusTrackingTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = C89C5FC91D06CECD002AAAD2 /* StatusTrackingTableViewCell.swift */; };
|
||||
C89C5FCC1D06CF0C002AAAD2 /* GPSAccuracyTrackingTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = C89C5FCB1D06CF0C002AAAD2 /* GPSAccuracyTrackingTableViewCell.swift */; };
|
||||
@@ -391,7 +396,7 @@
|
||||
6010190FF03AFE91478240B4 /* Pods-SAPTrackerTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SAPTrackerTests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-SAPTrackerTests/Pods-SAPTrackerTests.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
7F03FD3F19FA4D7400FA1327 /* bridge.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = bridge.h; sourceTree = "<group>"; };
|
||||
7F0658FC19F7D6700077FF95 /* ScanViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = ScanViewController.swift; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.swift; };
|
||||
7F0658FE19F7EE910077FF95 /* CheckInData.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = CheckInData.swift; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.swift; };
|
||||
7F0658FE19F7EE910077FF95 /* RegattaData.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = RegattaData.swift; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.swift; };
|
||||
7F14A0041A13B9A6001C1ECB /* _abkhazia.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = _abkhazia.png; sourceTree = "<group>"; };
|
||||
7F14A0051A13B9A6001C1ECB /* _basque-country.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "_basque-country.png"; sourceTree = "<group>"; };
|
||||
7F14A0061A13B9A6001C1ECB /* _british-antarctic-territory.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "_british-antarctic-territory.png"; sourceTree = "<group>"; };
|
||||
@@ -700,7 +705,6 @@
|
||||
C852BAAA1CF736680093B0C5 /* Preferences.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Preferences.swift; sourceTree = "<group>"; };
|
||||
C8603D491C528832002B2F28 /* Acknowledgements.markdown */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; path = Acknowledgements.markdown; sourceTree = "<group>"; };
|
||||
C8739D891D21276B00A89F3C /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = de.lproj/Main.strings; sourceTree = "<group>"; };
|
||||
C8739D8D1D23D53C00A89F3C /* SendGPSFixesController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SendGPSFixesController.swift; sourceTree = "<group>"; };
|
||||
C8739D9A1D25317100A89F3C /* CoreData 2.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = "CoreData 2.xcdatamodel"; sourceTree = "<group>"; };
|
||||
C8739DFA1D2AA2A500A89F3C /* Regatta+CoreDataProperties.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Regatta+CoreDataProperties.swift"; sourceTree = "<group>"; };
|
||||
C8739DFB1D2AA2A500A89F3C /* Regatta.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Regatta.swift; sourceTree = "<group>"; };
|
||||
@@ -712,6 +716,12 @@
|
||||
C8739E011D2AA2A500A89F3C /* Competitor.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Competitor.swift; sourceTree = "<group>"; };
|
||||
C8739E021D2AA2A500A89F3C /* Event+CoreDataProperties.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Event+CoreDataProperties.swift"; sourceTree = "<group>"; };
|
||||
C8739E031D2AA2A500A89F3C /* Event.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Event.swift; sourceTree = "<group>"; };
|
||||
C8739E0E1D2BEE7900A89F3C /* RegattaController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RegattaController.swift; sourceTree = "<group>"; };
|
||||
C8739E111D2BF14F00A89F3C /* EventData.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EventData.swift; sourceTree = "<group>"; };
|
||||
C8739E131D2BF16300A89F3C /* LeaderboardData.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LeaderboardData.swift; sourceTree = "<group>"; };
|
||||
C8739E151D2BF17900A89F3C /* CompetitorData.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CompetitorData.swift; sourceTree = "<group>"; };
|
||||
C8739E171D2BF2DC00A89F3C /* BaseData.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BaseData.swift; sourceTree = "<group>"; };
|
||||
C8739E1B1D2D5F1700A89F3C /* LocationData.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LocationData.swift; sourceTree = "<group>"; };
|
||||
C89C5FC41D06A289002AAAD2 /* GradientView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GradientView.swift; sourceTree = "<group>"; };
|
||||
C89C5FC91D06CECD002AAAD2 /* StatusTrackingTableViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StatusTrackingTableViewCell.swift; sourceTree = "<group>"; };
|
||||
C89C5FCB1D06CF0C002AAAD2 /* GPSAccuracyTrackingTableViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GPSAccuracyTrackingTableViewCell.swift; sourceTree = "<group>"; };
|
||||
@@ -793,9 +803,10 @@
|
||||
7F06590219F7FEA40077FF95 /* DataController */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
C8739D8A1D22CCDB00A89F3C /* GPSFixes */,
|
||||
C8739E0E1D2BEE7900A89F3C /* RegattaController.swift */,
|
||||
7F23F0871A1A3DEF00F03F1C /* CheckInController.swift */,
|
||||
C8739E101D2BF13200A89F3C /* Data */,
|
||||
C852BAA61CF5E1F40093B0C5 /* CheckIn */,
|
||||
7F1B66F81A0CDCF600904A41 /* BatteryManager.swift */,
|
||||
);
|
||||
name = DataController;
|
||||
sourceTree = "<group>";
|
||||
@@ -1162,8 +1173,6 @@
|
||||
C852BAA61CF5E1F40093B0C5 /* CheckIn */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
7F0658FE19F7EE910077FF95 /* CheckInData.swift */,
|
||||
7F23F0871A1A3DEF00F03F1C /* CheckInController.swift */,
|
||||
);
|
||||
name = CheckIn;
|
||||
sourceTree = "<group>";
|
||||
@@ -1176,17 +1185,11 @@
|
||||
name = Preferences;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
C8739D8A1D22CCDB00A89F3C /* GPSFixes */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
C8739D8D1D23D53C00A89F3C /* SendGPSFixesController.swift */,
|
||||
);
|
||||
name = GPSFixes;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
C8739D8B1D23C01500A89F3C /* Managers */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
7F2C605919F160E400C32D93 /* LocationManager.swift */,
|
||||
7F1B66F81A0CDCF600904A41 /* BatteryManager.swift */,
|
||||
C852BAA11CF5E1EA0093B0C5 /* RequestManager.swift */,
|
||||
);
|
||||
name = Managers;
|
||||
@@ -1200,20 +1203,11 @@
|
||||
name = EULA;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
C8739DC61D2A650E00A89F3C /* Location */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
7F2C605919F160E400C32D93 /* LocationManager.swift */,
|
||||
);
|
||||
name = Location;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
C8739DC71D2A653F00A89F3C /* Classes */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
7F06590019F7FE750077FF95 /* CoreData */,
|
||||
7F06590219F7FEA40077FF95 /* DataController */,
|
||||
C8739DC61D2A650E00A89F3C /* Location */,
|
||||
C8739D8B1D23C01500A89F3C /* Managers */,
|
||||
C852BAA91CF736440093B0C5 /* Preferences */,
|
||||
7F06590119F7FE920077FF95 /* ViewController */,
|
||||
@@ -1222,6 +1216,19 @@
|
||||
name = Classes;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
C8739E101D2BF13200A89F3C /* Data */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
7F0658FE19F7EE910077FF95 /* RegattaData.swift */,
|
||||
C8739E111D2BF14F00A89F3C /* EventData.swift */,
|
||||
C8739E131D2BF16300A89F3C /* LeaderboardData.swift */,
|
||||
C8739E151D2BF17900A89F3C /* CompetitorData.swift */,
|
||||
C8739E171D2BF2DC00A89F3C /* BaseData.swift */,
|
||||
C8739E1B1D2D5F1700A89F3C /* LocationData.swift */,
|
||||
);
|
||||
name = Data;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
C89C5FC31D06A269002AAAD2 /* Views */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@@ -1847,9 +1854,13 @@
|
||||
files = (
|
||||
7F1875B31A10F1B800C25BE0 /* TrackingViewController.swift in Sources */,
|
||||
C8739E081D2AA2A500A89F3C /* Leaderboard+CoreDataProperties.swift in Sources */,
|
||||
C8739E121D2BF14F00A89F3C /* EventData.swift in Sources */,
|
||||
C8739E0F1D2BEE7900A89F3C /* RegattaController.swift in Sources */,
|
||||
C8739E1C1D2D5F1700A89F3C /* LocationData.swift in Sources */,
|
||||
7F83F15819F154F000C53328 /* HomeViewController.swift in Sources */,
|
||||
7F8B8D431A373D4400C34B88 /* CourseViewController.swift in Sources */,
|
||||
7FAFA7951A126B5700D230F1 /* AboutViewController.swift in Sources */,
|
||||
C8739E161D2BF17900A89F3C /* CompetitorData.swift in Sources */,
|
||||
C8739E0A1D2AA2A500A89F3C /* Competitor+CoreDataProperties.swift in Sources */,
|
||||
C8739E0C1D2AA2A500A89F3C /* Event+CoreDataProperties.swift in Sources */,
|
||||
C8739E071D2AA2A500A89F3C /* GPSFix.swift in Sources */,
|
||||
@@ -1859,7 +1870,6 @@
|
||||
7FA6551A19F6661900A1B92D /* CoreDataManager.swift in Sources */,
|
||||
C852BAA21CF5E1EA0093B0C5 /* RequestManager.swift in Sources */,
|
||||
C8BBAC791C52649E004CA551 /* LicenseViewController.swift in Sources */,
|
||||
C8739D8E1D23D53C00A89F3C /* SendGPSFixesController.swift in Sources */,
|
||||
7F23F0881A1A3DEF00F03F1C /* CheckInController.swift in Sources */,
|
||||
7F2C605A19F160E400C32D93 /* LocationManager.swift in Sources */,
|
||||
C89C5FCC1D06CF0C002AAAD2 /* GPSAccuracyTrackingTableViewCell.swift in Sources */,
|
||||
@@ -1874,16 +1884,18 @@
|
||||
9E95C3D61C723AB30016632B /* Constants.swift in Sources */,
|
||||
7FD9D3031A1236080058FEAD /* Extensions.swift in Sources */,
|
||||
C8739E091D2AA2A500A89F3C /* Leaderboard.swift in Sources */,
|
||||
C8739E141D2BF16300A89F3C /* LeaderboardData.swift in Sources */,
|
||||
C89C5FC51D06A289002AAAD2 /* GradientView.swift in Sources */,
|
||||
C852BAAB1CF736680093B0C5 /* Preferences.swift in Sources */,
|
||||
7F0658FD19F7D6700077FF95 /* ScanViewController.swift in Sources */,
|
||||
C8739E061D2AA2A500A89F3C /* GPSFix+CoreDataProperties.swift in Sources */,
|
||||
7F193A8F1A39ACF500D71773 /* TimerViewController.swift in Sources */,
|
||||
C8739E181D2BF2DC00A89F3C /* BaseData.swift in Sources */,
|
||||
7F83F15619F154F000C53328 /* AppDelegate.swift in Sources */,
|
||||
7F950A911A35E967003C8C5C /* LeaderboardViewController.swift in Sources */,
|
||||
C89C5FCE1D06CF26002AAAD2 /* CachedFixesTrackingTableViewCell.swift in Sources */,
|
||||
C8739E0B1D2AA2A500A89F3C /* Competitor.swift in Sources */,
|
||||
7F0658FF19F7EE910077FF95 /* CheckInData.swift in Sources */,
|
||||
7F0658FF19F7EE910077FF95 /* RegattaData.swift in Sources */,
|
||||
7F193A911A39E54600D71773 /* GPSAccuracyView.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
//
|
||||
// BaseData.swift
|
||||
// SAPTracker
|
||||
//
|
||||
// Created by Raimund Wege on 05.07.16.
|
||||
// Copyright © 2016 com.sap.sailing. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
class BaseData: NSObject {
|
||||
|
||||
let dictionary: [String: AnyObject]
|
||||
|
||||
override init() {
|
||||
self.dictionary = [String: AnyObject]()
|
||||
super.init()
|
||||
}
|
||||
|
||||
init(dictionary: [String: AnyObject]?) {
|
||||
self.dictionary = dictionary ?? [String: AnyObject]()
|
||||
super.init()
|
||||
}
|
||||
|
||||
func doubleValue(forKey key: String) -> Double {
|
||||
return dictionary[key] as? Double ?? 0.0
|
||||
}
|
||||
|
||||
func stringValue(forKey key: String) -> String {
|
||||
return dictionary[key] as? String ?? ""
|
||||
}
|
||||
|
||||
}
|
||||
@@ -35,8 +35,9 @@ class CachedFixesTrackingTableViewCell: UITableViewCell {
|
||||
private func subscribeForNotifications() {
|
||||
NSNotificationCenter.defaultCenter().addObserver(self,
|
||||
selector:#selector(locationManagerUpdated(_:)),
|
||||
name:LocationManager.NotificationType.LocationManagerUpdated,
|
||||
object: nil)
|
||||
name:LocationManager.NotificationType.Updated,
|
||||
object: nil
|
||||
)
|
||||
}
|
||||
|
||||
private func unsubscribeFromNotifications() {
|
||||
|
||||
@@ -21,134 +21,26 @@ import AVFoundation
|
||||
|
||||
class CheckInController : NSObject {
|
||||
|
||||
private struct EventKeys {
|
||||
static let EndDate = "endDate"
|
||||
static let ID = "id"
|
||||
static let ImageURLs = "imageURLs"
|
||||
static let Name = "name"
|
||||
static let StartDate = "startDate"
|
||||
}
|
||||
|
||||
private struct CompetitorKeys {
|
||||
static let BoatClassName = "boatClassName"
|
||||
static let CountryCode = "countryCode"
|
||||
static let ID = "id"
|
||||
static let Name = "name"
|
||||
static let Nationality = "nationality"
|
||||
static let SailID = "sailID"
|
||||
}
|
||||
|
||||
private struct LeaderboardKeys {
|
||||
static let Name = "name"
|
||||
}
|
||||
|
||||
var delegate: CheckInControllerDelegate?
|
||||
|
||||
private var checkInData = CheckInData()
|
||||
private var requestManager = RequestManager()
|
||||
|
||||
// Responses
|
||||
private var eventDictionary: [String: AnyObject]?
|
||||
private var leaderboardDictionary: [String: AnyObject]?
|
||||
private var competitorDictionary: [String: AnyObject]?
|
||||
private var teamImageURL: String?
|
||||
// MARK: - CheckIn
|
||||
|
||||
// MARK: - Initialize
|
||||
|
||||
private func initialize(checkInData: CheckInData) {
|
||||
self.checkInData = checkInData
|
||||
setupRequestManager()
|
||||
}
|
||||
|
||||
// MARK: - Setups
|
||||
|
||||
private func setupRequestManager() {
|
||||
requestManager = RequestManager(baseURLString: checkInData.serverURL)
|
||||
}
|
||||
|
||||
// MARK: - Start check-in
|
||||
|
||||
func startCheckIn(checkInData: CheckInData) {
|
||||
initialize(checkInData)
|
||||
func checkIn(regattaData: RegattaData) {
|
||||
checkInDidStart()
|
||||
requestManager.getEvent(checkInData.eventID,
|
||||
success: { (operation, responseObject) -> Void in self.eventSucceed(responseObject) },
|
||||
failure: { (operation, error) -> Void in self.eventFailed(error) }
|
||||
requestManager = RequestManager(baseURLString: regattaData.serverURL)
|
||||
requestManager.getRegattaData(regattaData,
|
||||
success: { (regattaData) in self.checkInSuccess(regattaData) },
|
||||
failure: { (title, error) in self.checkInFailure(title, error: error) }
|
||||
)
|
||||
}
|
||||
|
||||
// MARK: - Event
|
||||
|
||||
private func eventSucceed(eventResponseObject: AnyObject) {
|
||||
eventDictionary = eventResponseObject as? [String: AnyObject]
|
||||
requestManager.getLeaderboard(checkInData.leaderboardName,
|
||||
success: { (operation, responseObject) -> Void in self.leaderboardSucceed(responseObject) },
|
||||
failure: { (operation, error) -> Void in self.leaderboardFailed(error) }
|
||||
)
|
||||
}
|
||||
|
||||
private func eventFailed(error: AnyObject) {
|
||||
let alertTitle = String(format: NSLocalizedString("Couldn't get event %@", comment: ""), checkInData.eventID)
|
||||
let alertController = UIAlertController(title: alertTitle, message: error.localizedDescription, preferredStyle: .Alert)
|
||||
let cancelTitle = NSLocalizedString("Cancel", comment: "")
|
||||
let cancelAction = UIAlertAction(title: cancelTitle, style: .Cancel) { (action) in
|
||||
self.checkInDidEnd(withSuccess: false)
|
||||
}
|
||||
alertController.addAction(cancelAction)
|
||||
showCheckInAlert(alertController)
|
||||
}
|
||||
|
||||
// MARK: - Leaderboard
|
||||
|
||||
private func leaderboardSucceed(leaderboardResponseObject: AnyObject) {
|
||||
leaderboardDictionary = leaderboardResponseObject as? [String: AnyObject]
|
||||
requestManager.getCompetitor(checkInData.competitorID,
|
||||
success: { (operation, responseObject) in self.competitorSucceed(responseObject) },
|
||||
failure: { (operation, error) in self.competitorFailed(error) }
|
||||
)
|
||||
}
|
||||
|
||||
private func leaderboardFailed(error: AnyObject) {
|
||||
let alertTitle = String(format: NSLocalizedString("Couldn't get leader board %@", comment: ""), checkInData.leaderboardName)
|
||||
let alertController = UIAlertController(title: alertTitle, message: error.localizedDescription, preferredStyle: .Alert)
|
||||
let cancelTitle = NSLocalizedString("Cancel", comment: "")
|
||||
let cancelAction = UIAlertAction(title: cancelTitle, style: .Cancel) { (action) in
|
||||
self.checkInDidEnd(withSuccess: false)
|
||||
}
|
||||
alertController.addAction(cancelAction)
|
||||
showCheckInAlert(alertController)
|
||||
}
|
||||
|
||||
// MARK: - Competitor
|
||||
|
||||
private func competitorSucceed(competitorResponseObject: AnyObject) {
|
||||
competitorDictionary = competitorResponseObject as? [String: AnyObject]
|
||||
requestManager.getTeamImageURL(competitorID, result: { (imageURL) in self.teamImageURLResult(imageURL) })
|
||||
}
|
||||
|
||||
private func competitorFailed(error: AnyObject) {
|
||||
let alertTitle = String(format: NSLocalizedString("Couldn't get competitor %@", comment: ""), checkInData.competitorID)
|
||||
let alertController = UIAlertController(title: alertTitle, message: error.localizedDescription, preferredStyle: .Alert)
|
||||
let cancelTitle = NSLocalizedString("Cancel", comment: "")
|
||||
let cancelAction = UIAlertAction(title: cancelTitle, style: .Cancel) { (action) in
|
||||
self.checkInDidEnd(withSuccess: false)
|
||||
}
|
||||
alertController.addAction(cancelAction)
|
||||
showCheckInAlert(alertController)
|
||||
}
|
||||
|
||||
// MARK: - Team
|
||||
|
||||
private func teamImageURLResult(imageURL: String?) {
|
||||
teamImageURL = imageURL
|
||||
let alertTitle = String(format:NSLocalizedString("Hello %@. Welcome to %@. You are registered as %@.", comment: ""),
|
||||
competitorName,
|
||||
leaderboardName,
|
||||
competitorSailID)
|
||||
let alertController = UIAlertController(title: alertTitle, message: nil, preferredStyle: .Alert)
|
||||
private func checkInSuccess(regattaData: RegattaData) {
|
||||
let alertController = UIAlertController(title: regattaData.welcomeString, message: nil, preferredStyle: .Alert)
|
||||
let okTitle = NSLocalizedString("OK", comment: "")
|
||||
let okAction = UIAlertAction(title: okTitle, style: .Default) { (action) in
|
||||
self.checkInOnServer()
|
||||
self.postCheckIn(regattaData)
|
||||
}
|
||||
let cancelTitle = NSLocalizedString("Cancel", comment: "")
|
||||
let cancelAction = UIAlertAction(title: cancelTitle, style: .Cancel) { (action) in
|
||||
@@ -159,47 +51,45 @@ class CheckInController : NSObject {
|
||||
showCheckInAlert(alertController)
|
||||
}
|
||||
|
||||
// MARK: - Check-in on server
|
||||
private func checkInFailure(title: String, error: NSError) {
|
||||
let alertController = UIAlertController(title: title, message: error.localizedDescription, preferredStyle: .Alert)
|
||||
let cancelTitle = NSLocalizedString("Cancel", comment: "")
|
||||
let cancelAction = UIAlertAction(title: cancelTitle, style: .Cancel) { (action) in
|
||||
self.checkInDidEnd(withSuccess: false)
|
||||
}
|
||||
alertController.addAction(cancelAction)
|
||||
showCheckInAlert(alertController)
|
||||
}
|
||||
|
||||
private func checkInOnServer() {
|
||||
private func postCheckIn(regattaData: RegattaData) {
|
||||
SVProgressHUD.show()
|
||||
requestManager.postCheckIn(leaderboardName,
|
||||
competitorID: competitorID,
|
||||
success: { (operation, responseObject) -> Void in self.checkInOnServerSucceed() },
|
||||
failure: { (operation, error) -> Void in self.checkInOnServerFailed(error) }
|
||||
requestManager.postCheckIn(regattaData.leaderboardData.name,
|
||||
competitorID: regattaData.competitorData.competitorID,
|
||||
success: { (operation, responseObject) -> Void in self.postCheckInSuccess(regattaData) },
|
||||
failure: { (operation, error) -> Void in self.postCheckInFailure(regattaData, error: error) }
|
||||
)
|
||||
}
|
||||
|
||||
private func checkInOnServerSucceed() {
|
||||
private func postCheckInSuccess(regattaData: RegattaData) {
|
||||
|
||||
// Regatta
|
||||
let regatta = CoreDataManager.sharedManager.fetchRegatta(checkInData.eventID,
|
||||
leaderboardName: checkInData.leaderboardName,
|
||||
competitorID: checkInData.competitorID
|
||||
let regatta = CoreDataManager.sharedManager.fetchRegatta(regattaData.eventID,
|
||||
leaderboardName: regattaData.leaderboardName,
|
||||
competitorID: regattaData.competitorID
|
||||
) ?? CoreDataManager.sharedManager.newRegatta()
|
||||
regatta.serverURL = checkInData.serverURL
|
||||
regatta.teamImageURL = teamImageURL
|
||||
regatta.teamImageRetry = false
|
||||
regatta.updateWirhRegattaData(regattaData)
|
||||
|
||||
// Event
|
||||
let event = regatta.event ?? CoreDataManager.sharedManager.newEvent(regatta)
|
||||
event.endDate = (eventEndDate / 1000)
|
||||
event.eventID = eventID
|
||||
event.name = eventName
|
||||
event.startDate = (eventStartDate / 1000)
|
||||
event.updateWithEventData(regattaData.eventData)
|
||||
|
||||
// Leaderboard
|
||||
let leaderboard = regatta.leaderboard ?? CoreDataManager.sharedManager.newLeaderboard(regatta)
|
||||
leaderboard.name = leaderboardName
|
||||
leaderboard.updateWithLeaderboardData(regattaData.leaderboardData)
|
||||
|
||||
// Competitor
|
||||
let competitor = regatta.competitor ?? CoreDataManager.sharedManager.newCompetitor(regatta)
|
||||
competitor.boatClassName = competitorBoatClassName
|
||||
competitor.competitorID = competitorID
|
||||
competitor.countryCode = competitorCountryCode
|
||||
competitor.name = competitorName
|
||||
competitor.nationality = competitorNationality
|
||||
competitor.sailID = competitorSailID
|
||||
competitor.updateWithCompetitorData(regattaData.competitorData)
|
||||
|
||||
// Save
|
||||
CoreDataManager.sharedManager.saveContext()
|
||||
@@ -208,8 +98,8 @@ class CheckInController : NSObject {
|
||||
checkInDidEnd(withSuccess: true)
|
||||
}
|
||||
|
||||
private func checkInOnServerFailed(error: AnyObject) {
|
||||
let alertTitle = String(format:NSLocalizedString("Couldn't check-in to %@", comment: ""), checkInData.leaderboardName)
|
||||
private func postCheckInFailure(regattaData: RegattaData, error: AnyObject) {
|
||||
let alertTitle = String(format:NSLocalizedString("Couldn't check-in to %@", comment: ""), regattaData.leaderboardName)
|
||||
let alertController = UIAlertController(title: alertTitle, message: error.localizedDescription, preferredStyle: .Alert)
|
||||
let cancelTitle = NSLocalizedString("Cancel", comment: "")
|
||||
let cancelAction = UIAlertAction(title: cancelTitle, style: .Cancel) { (action) in
|
||||
@@ -222,67 +112,18 @@ class CheckInController : NSObject {
|
||||
// MARK: - Controller
|
||||
|
||||
private func checkInDidStart() {
|
||||
dispatch_async(dispatch_get_main_queue(), {
|
||||
SVProgressHUD.show()
|
||||
self.delegate?.checkInDidStart?(self)
|
||||
})
|
||||
}
|
||||
|
||||
private func checkInDidEnd(withSuccess succeed: Bool) {
|
||||
dispatch_async(dispatch_get_main_queue(), {
|
||||
SVProgressHUD.popActivity()
|
||||
self.delegate?.checkInDidEnd?(self, withSuccess: succeed)
|
||||
})
|
||||
}
|
||||
|
||||
private func showCheckInAlert(alertController: UIAlertController) {
|
||||
dispatch_async(dispatch_get_main_queue(), {
|
||||
SVProgressHUD.popActivity()
|
||||
self.delegate?.showCheckInAlert(self, alertController: alertController)
|
||||
})
|
||||
}
|
||||
|
||||
// MARK: - Event
|
||||
|
||||
var eventID: String { get { return stringFromEvent(forKey: EventKeys.ID) } }
|
||||
var eventName: String { get { return stringFromEvent(forKey: EventKeys.Name) } }
|
||||
var eventStartDate: Double { get { return doubleFromEvent(forKey: EventKeys.StartDate) } }
|
||||
var eventEndDate: Double { get { return doubleFromEvent(forKey: EventKeys.EndDate) } }
|
||||
|
||||
// MARK: - Leaderboard
|
||||
|
||||
var leaderboardName: String { get { return stringFromLeaderboard(forKey: LeaderboardKeys.Name) } }
|
||||
|
||||
// MARK: - Competitor
|
||||
|
||||
var competitorBoatClassName: String { get { return stringFromCompetitor(forKey: CompetitorKeys.BoatClassName) } }
|
||||
var competitorCountryCode: String { get { return stringFromCompetitor(forKey: CompetitorKeys.CountryCode) } }
|
||||
var competitorID: String { get { return stringFromCompetitor(forKey: CompetitorKeys.ID) } }
|
||||
var competitorName: String { get { return stringFromCompetitor(forKey: CompetitorKeys.Name) } }
|
||||
var competitorNationality: String { get { return stringFromCompetitor(forKey: CompetitorKeys.Nationality) } }
|
||||
var competitorSailID: String { get { return stringFromCompetitor(forKey: CompetitorKeys.SailID) } }
|
||||
|
||||
// MARK: - Helper
|
||||
|
||||
private func doubleFromEvent(forKey key: String) -> Double { return doubleFromDictionary(eventDictionary, forKey: key) }
|
||||
private func stringFromEvent(forKey key: String) -> String { return stringFromDictionary(eventDictionary, forKey: key) }
|
||||
private func stringFromLeaderboard(forKey key: String) -> String { return stringFromDictionary(leaderboardDictionary, forKey: key) }
|
||||
private func stringFromCompetitor(forKey key: String) -> String { return stringFromDictionary(competitorDictionary, forKey: key) }
|
||||
|
||||
private func doubleFromDictionary(dictionary: [String: AnyObject]?, forKey key: String) -> Double {
|
||||
if let value = dictionary?[key] as? Double {
|
||||
return value
|
||||
} else {
|
||||
return 0.0
|
||||
}
|
||||
}
|
||||
|
||||
private func stringFromDictionary(dictionary: [String: AnyObject]?, forKey key: String) -> String {
|
||||
if let value = dictionary?[key] as? String {
|
||||
return value
|
||||
} else {
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -12,6 +12,13 @@ import CoreData
|
||||
@objc(Competitor)
|
||||
class Competitor: NSManagedObject {
|
||||
|
||||
// Insert code here to add functionality to your managed object subclass
|
||||
func updateWithCompetitorData(competitorData: CompetitorData) {
|
||||
boatClassName = competitorData.boatClassName
|
||||
competitorID = competitorData.competitorID
|
||||
countryCode = competitorData.countryCode
|
||||
name = competitorData.name
|
||||
nationality = competitorData.nationality
|
||||
sailID = competitorData.sailID
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
//
|
||||
// CompetitorData.swift
|
||||
// SAPTracker
|
||||
//
|
||||
// Created by Raimund Wege on 05.07.16.
|
||||
// Copyright © 2016 com.sap.sailing. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
class CompetitorData: BaseData {
|
||||
|
||||
private struct Keys {
|
||||
static let BoatClassName = "boatClassName"
|
||||
static let CountryCode = "countryCode"
|
||||
static let ID = "id"
|
||||
static let Name = "name"
|
||||
static let Nationality = "nationality"
|
||||
static let SailID = "sailID"
|
||||
}
|
||||
|
||||
var boatClassName: String { get { return stringValue(forKey: Keys.BoatClassName) } }
|
||||
var countryCode: String { get { return stringValue(forKey: Keys.CountryCode) } }
|
||||
var competitorID: String { get { return stringValue(forKey: Keys.ID) } }
|
||||
var name: String { get { return stringValue(forKey: Keys.Name) } }
|
||||
var nationality: String { get { return stringValue(forKey: Keys.Nationality) } }
|
||||
var sailID: String { get { return stringValue(forKey: Keys.SailID) } }
|
||||
|
||||
}
|
||||
@@ -35,7 +35,11 @@ class CourseViewController: UIViewController {
|
||||
private func subscribeForNotifications() {
|
||||
NSNotificationCenter.defaultCenter().addObserver(self,
|
||||
selector:#selector(locationManagerUpdated(_:)),
|
||||
name:LocationManager.NotificationType.LocationManagerUpdated,
|
||||
name:LocationManager.NotificationType.Updated,
|
||||
object: nil)
|
||||
NSNotificationCenter.defaultCenter().addObserver(self,
|
||||
selector:#selector(locationManagerFailed(_:)),
|
||||
name:LocationManager.NotificationType.Failed,
|
||||
object: nil)
|
||||
}
|
||||
|
||||
@@ -45,7 +49,14 @@ class CourseViewController: UIViewController {
|
||||
|
||||
func locationManagerUpdated(notification: NSNotification) {
|
||||
dispatch_async(dispatch_get_main_queue(), {
|
||||
self.setupCourseLabel(notification.userInfo![LocationManager.UserInfo.Course] as! Double)
|
||||
guard let locationData = notification.userInfo?[LocationManager.UserInfo.LocationData] as? LocationData else { return }
|
||||
self.setupCourseLabel(locationData.location.course)
|
||||
})
|
||||
}
|
||||
|
||||
func locationManagerFailed(notification: NSNotification) {
|
||||
dispatch_async(dispatch_get_main_queue(), {
|
||||
self.setupCourseLabel(-1.0)
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -12,6 +12,11 @@ import CoreData
|
||||
@objc(Event)
|
||||
class Event: NSManagedObject {
|
||||
|
||||
// Insert code here to add functionality to your managed object subclass
|
||||
func updateWithEventData(eventData: EventData) {
|
||||
endDate = eventData.endDate
|
||||
eventID = eventData.eventID
|
||||
name = eventData.name
|
||||
startDate = eventData.startDate
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
//
|
||||
// EventData.swift
|
||||
// SAPTracker
|
||||
//
|
||||
// Created by Raimund Wege on 05.07.16.
|
||||
// Copyright © 2016 com.sap.sailing. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
class EventData: BaseData {
|
||||
|
||||
private struct Keys {
|
||||
static let EndDate = "endDate"
|
||||
static let ID = "id"
|
||||
static let ImageURLs = "imageURLs"
|
||||
static let Name = "name"
|
||||
static let StartDate = "startDate"
|
||||
}
|
||||
|
||||
var endDate: Double { get { return doubleValue(forKey: Keys.EndDate) / 1000 } }
|
||||
var eventID: String { get { return stringValue(forKey: Keys.ID) } }
|
||||
var name: String { get { return stringValue(forKey: Keys.Name) } }
|
||||
var startDate: Double { get { return doubleValue(forKey: Keys.StartDate) / 1000 } }
|
||||
|
||||
}
|
||||
@@ -38,12 +38,14 @@ class GPSAccuracyTrackingTableViewCell: UITableViewCell {
|
||||
private func subscribeForNotifications() {
|
||||
NSNotificationCenter.defaultCenter().addObserver(self,
|
||||
selector:#selector(locationManagerUpdated(_:)),
|
||||
name:LocationManager.NotificationType.LocationManagerUpdated,
|
||||
object: nil)
|
||||
name:LocationManager.NotificationType.Updated,
|
||||
object: nil
|
||||
)
|
||||
NSNotificationCenter.defaultCenter().addObserver(self,
|
||||
selector:#selector(locationManagerFailed(_:)),
|
||||
name:LocationManager.NotificationType.LocationManagerFailed,
|
||||
object: nil)
|
||||
name:LocationManager.NotificationType.Failed,
|
||||
object: nil
|
||||
)
|
||||
}
|
||||
|
||||
private func unsubscribeFromNotifications() {
|
||||
@@ -52,7 +54,8 @@ class GPSAccuracyTrackingTableViewCell: UITableViewCell {
|
||||
|
||||
func locationManagerUpdated(notification: NSNotification) {
|
||||
dispatch_async(dispatch_get_main_queue(), {
|
||||
self.setupGPSAccuracyLabel(notification.userInfo![LocationManager.UserInfo.HorizontalAccuracy] as! Double)
|
||||
guard let locationData = notification.userInfo?[LocationManager.UserInfo.LocationData] as? LocationData else { return }
|
||||
self.setupGPSAccuracyLabel(locationData.location.horizontalAccuracy)
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -58,12 +58,14 @@ class GPSAccuracyView : UIView {
|
||||
private func subscribeForNotifications() {
|
||||
NSNotificationCenter.defaultCenter().addObserver(self,
|
||||
selector:#selector(locationManagerUpdated(_:)),
|
||||
name:LocationManager.NotificationType.LocationManagerUpdated,
|
||||
object: nil)
|
||||
name:LocationManager.NotificationType.Updated,
|
||||
object: nil
|
||||
)
|
||||
NSNotificationCenter.defaultCenter().addObserver(self,
|
||||
selector:#selector(locationManagerFailed(_:)),
|
||||
name:LocationManager.NotificationType.LocationManagerFailed,
|
||||
object: nil)
|
||||
name:LocationManager.NotificationType.Failed,
|
||||
object: nil
|
||||
)
|
||||
}
|
||||
|
||||
private func unsubscribeFromNotifications() {
|
||||
@@ -72,7 +74,8 @@ class GPSAccuracyView : UIView {
|
||||
|
||||
func locationManagerUpdated(notification: NSNotification) {
|
||||
dispatch_async(dispatch_get_main_queue(), {
|
||||
self.drawBar(notification.userInfo![LocationManager.UserInfo.HorizontalAccuracy] as! Double)
|
||||
guard let locationData = notification.userInfo?[LocationManager.UserInfo.LocationData] as? LocationData else { return }
|
||||
self.drawBar(locationData.location.horizontalAccuracy)
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -12,6 +12,12 @@ import CoreData
|
||||
@objc(GPSFix)
|
||||
class GPSFix: NSManagedObject {
|
||||
|
||||
// Insert code here to add functionality to your managed object subclass
|
||||
func updateWithLocationData(locationData: LocationData) {
|
||||
course = locationData.location.course
|
||||
latitude = locationData.location.coordinate.latitude
|
||||
longitude = locationData.location.coordinate.longitude
|
||||
speed = locationData.location.speed
|
||||
timestamp = round(locationData.location.timestamp.timeIntervalSince1970 * 1000)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -84,7 +84,7 @@ class HomeViewController: UIViewController {
|
||||
let viewTitle = NSLocalizedString("EULA_view", comment: "")
|
||||
let viewAction = UIAlertAction(title: viewTitle, style: .Cancel, handler: { action in
|
||||
UIApplication.sharedApplication().openURL(URLs.EULA)
|
||||
self.reviewEULA() // Reopen alert
|
||||
self.reviewEULA() // Reopen alert again until user confirms
|
||||
})
|
||||
let confirmTitle = NSLocalizedString("EULA_confirm", comment: "")
|
||||
let confirmAction = UIAlertAction(title: confirmTitle, style: .Default, handler: { action in
|
||||
@@ -99,8 +99,8 @@ class HomeViewController: UIViewController {
|
||||
func reviewNewCheckIn() {
|
||||
guard Preferences.termsAccepted else { return }
|
||||
guard let urlString = Preferences.newCheckInURL else { return }
|
||||
guard let checkInData = CheckInData(urlString: urlString) else { return }
|
||||
checkInController.startCheckIn(checkInData)
|
||||
guard let regattaData = RegattaData(urlString: urlString) else { return }
|
||||
checkInController.checkIn(regattaData)
|
||||
}
|
||||
|
||||
// MARK: - Notifications
|
||||
@@ -126,22 +126,15 @@ class HomeViewController: UIViewController {
|
||||
|
||||
@IBAction func optionButtonTap(sender: AnyObject) {
|
||||
let alertController = UIAlertController(title: nil, message: nil, preferredStyle: .ActionSheet)
|
||||
// FIXME: - what does this code?
|
||||
// if let popoverController = actionSheet.popoverPresentationController,
|
||||
// let barButtonItem = sender as? UIBarButtonItem {
|
||||
// popoverController.barButtonItem = barButtonItem
|
||||
// }
|
||||
// FIXME: - should be a simpler solution than dispatch with magic numbers
|
||||
if let popoverController = alertController.popoverPresentationController {
|
||||
popoverController.barButtonItem = sender as? UIBarButtonItem
|
||||
}
|
||||
let settingsAction = UIAlertAction(title: NSLocalizedString("Settings", comment: ""), style: .Default) { (action) -> Void in
|
||||
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, Int64(0.6 * Double(NSEC_PER_SEC))), dispatch_get_main_queue()) { () -> Void in
|
||||
self.performSegueWithIdentifier("SettingsFromHome", sender: alertController)
|
||||
}
|
||||
}
|
||||
let aboutAction = UIAlertAction(title: NSLocalizedString("About", comment: ""), style: .Default) { (action) -> Void in
|
||||
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, Int64(0.6 * Double(NSEC_PER_SEC))), dispatch_get_main_queue()) { () -> Void in
|
||||
self.performSegueWithIdentifier("AboutFromHome", sender: alertController)
|
||||
}
|
||||
}
|
||||
let cancelAction = UIAlertAction(title: NSLocalizedString("Cancel", comment: ""), style: .Cancel, handler: nil)
|
||||
alertController.addAction(settingsAction)
|
||||
alertController.addAction(aboutAction)
|
||||
@@ -159,7 +152,6 @@ class HomeViewController: UIViewController {
|
||||
let cancelAction = UIAlertAction(title: cancelTitle, style: .Cancel, handler: nil)
|
||||
alertController.addAction(cancelAction)
|
||||
presentViewController(alertController, animated: true, completion: nil)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -12,6 +12,10 @@ import CoreData
|
||||
@objc(Leaderboard)
|
||||
class Leaderboard: NSManagedObject {
|
||||
|
||||
func updateWithLeaderboardData(leaderboardData: LeaderboardData) {
|
||||
name = leaderboardData.name
|
||||
}
|
||||
|
||||
func nameWithQueryAllowedCharacters() -> String? {
|
||||
return name.stringByAddingPercentEncodingWithAllowedCharacters(.URLQueryAllowedCharacterSet())
|
||||
}
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
//
|
||||
// LeaderboardData.swift
|
||||
// SAPTracker
|
||||
//
|
||||
// Created by Raimund Wege on 05.07.16.
|
||||
// Copyright © 2016 com.sap.sailing. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
class LeaderboardData: BaseData {
|
||||
|
||||
private struct Keys {
|
||||
static let Name = "name"
|
||||
}
|
||||
|
||||
var name: String { get { return stringValue(forKey: Keys.Name) } }
|
||||
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
//
|
||||
// LocationData.swift
|
||||
// SAPTracker
|
||||
//
|
||||
// Created by Raimund Wege on 06.07.16.
|
||||
// Copyright © 2016 com.sap.sailing. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import CoreLocation
|
||||
|
||||
class LocationData: NSObject {
|
||||
|
||||
struct LocationValidation {
|
||||
static let requiredAccuracy: CLLocationAccuracy = 10
|
||||
static let maxElapsedTime: NSTimeInterval = 10
|
||||
}
|
||||
|
||||
var location: CLLocation
|
||||
|
||||
init(location: CLLocation) {
|
||||
self.location = location
|
||||
super.init()
|
||||
}
|
||||
|
||||
var isValid: Bool {
|
||||
get {
|
||||
guard location.horizontalAccuracy >= 0 && location.horizontalAccuracy <= LocationValidation.requiredAccuracy else { return false }
|
||||
guard location.timestamp.timeIntervalSinceDate(NSDate()) <= LocationValidation.maxElapsedTime else { return false }
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -12,10 +12,15 @@ import CoreLocation
|
||||
class LocationManager: NSObject {
|
||||
|
||||
struct NotificationType {
|
||||
static let LocationManagerStarted = "LocationManagerStarted"
|
||||
static let LocationManagerStopped = "LocationManagerStopped"
|
||||
static let LocationManagerUpdated = "LocationManagerUpdated"
|
||||
static let LocationManagerFailed = "LocationManagerFailed"
|
||||
static let Started = "LocationManager.Started"
|
||||
static let Stopped = "LocationManager.Stopped"
|
||||
static let Updated = "LocationManager.Updated"
|
||||
static let Failed = "LocationManager.Failed"
|
||||
}
|
||||
|
||||
struct UserInfo {
|
||||
static let Error = "NSError"
|
||||
static let LocationData = "LocationData"
|
||||
}
|
||||
|
||||
enum LocationManagerError: ErrorType {
|
||||
@@ -23,8 +28,8 @@ class LocationManager: NSObject {
|
||||
case LocationServicesDenied
|
||||
var description: String {
|
||||
switch self {
|
||||
case LocationManagerError.LocationServicesDenied: return NSLocalizedString("Please enable location services for this app.", comment: "")
|
||||
case LocationManagerError.LocationServicesDisabled: return NSLocalizedString("Please enable location services.", comment: "")
|
||||
case .LocationServicesDenied: return NSLocalizedString("Please enable location services for this app.", comment: "")
|
||||
case .LocationServicesDisabled: return NSLocalizedString("Please enable location services.", comment: "")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -74,7 +79,7 @@ class LocationManager: NSObject {
|
||||
isTracking = true;
|
||||
|
||||
// Send notification
|
||||
let notification = NSNotification(name: NotificationType.LocationManagerStarted, object: self)
|
||||
let notification = NSNotification(name: NotificationType.Started, object: self)
|
||||
NSNotificationQueue.defaultQueue().enqueueNotification(notification, postingStyle: NSPostingStyle.PostASAP)
|
||||
}
|
||||
|
||||
@@ -86,7 +91,7 @@ class LocationManager: NSObject {
|
||||
isTracking = false;
|
||||
|
||||
// Send notification
|
||||
let notification = NSNotification(name: NotificationType.LocationManagerStopped, object: self)
|
||||
let notification = NSNotification(name: NotificationType.Stopped, object: self)
|
||||
NSNotificationQueue.defaultQueue().enqueueNotification(notification, postingStyle: NSPostingStyle.PostASAP)
|
||||
}
|
||||
|
||||
@@ -96,50 +101,18 @@ class LocationManager: NSObject {
|
||||
|
||||
extension LocationManager: CLLocationManagerDelegate {
|
||||
|
||||
struct UserInfo {
|
||||
static let Error = "error"
|
||||
static let Course = "course"
|
||||
static let HorizontalAccuracy = "horizontalAccuracy"
|
||||
static let IsValid = "isValid"
|
||||
static let Latitude = "latitude"
|
||||
static let Longitude = "longitude"
|
||||
static let Speed = "speed"
|
||||
static let Timestamp = "timestamp"
|
||||
}
|
||||
|
||||
struct LocationValidation {
|
||||
static let requiredAccuracy: CLLocationAccuracy = 10
|
||||
static let maxElapsedTime: NSTimeInterval = 10
|
||||
}
|
||||
|
||||
func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
|
||||
let notification = NSNotification(name: NotificationType.LocationManagerUpdated, object: self, userInfo:dictionaryForLocation(locations.last!))
|
||||
guard let location = locations.last else { return }
|
||||
let locationData = LocationData(location: location)
|
||||
let userInfo = [UserInfo.LocationData: locationData]
|
||||
let notification = NSNotification(name: NotificationType.Updated, object: self, userInfo: userInfo)
|
||||
NSNotificationQueue.defaultQueue().enqueueNotification(notification, postingStyle: NSPostingStyle.PostASAP)
|
||||
}
|
||||
|
||||
func locationManager(manager: CLLocationManager, didFailWithError error: NSError) {
|
||||
let notification = NSNotification(name: NotificationType.LocationManagerFailed, object: self, userInfo: [UserInfo.Error: error])
|
||||
let userInfo = [UserInfo.Error: error]
|
||||
let notification = NSNotification(name: NotificationType.Failed, object: self, userInfo: userInfo)
|
||||
NSNotificationQueue.defaultQueue().enqueueNotification(notification, postingStyle: NSPostingStyle.PostASAP)
|
||||
}
|
||||
|
||||
// MARK: - Helper
|
||||
|
||||
private func dictionaryForLocation(location: CLLocation) -> [String: AnyObject] {
|
||||
return [
|
||||
UserInfo.Timestamp: location.timestamp.timeIntervalSince1970,
|
||||
UserInfo.Latitude : location.coordinate.latitude,
|
||||
UserInfo.Longitude: location.coordinate.longitude,
|
||||
UserInfo.Speed: location.speed,
|
||||
UserInfo.Course: location.course,
|
||||
UserInfo.HorizontalAccuracy: location.horizontalAccuracy,
|
||||
UserInfo.IsValid: isLocationValid(location)
|
||||
]
|
||||
}
|
||||
|
||||
private func isLocationValid(location: CLLocation) -> Bool {
|
||||
guard location.horizontalAccuracy >= 0 && location.horizontalAccuracy <= LocationValidation.requiredAccuracy else { return false }
|
||||
guard location.timestamp.timeIntervalSinceDate(NSDate()) <= LocationValidation.maxElapsedTime else { return false }
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -14,48 +14,39 @@ class ModeTrackingTableViewCell: UITableViewCell {
|
||||
|
||||
override func awakeFromNib() {
|
||||
super.awakeFromNib()
|
||||
self.setupModeLabel()
|
||||
// self.subscribeForNotifications()
|
||||
self.setupModeLabel(RegattaController.Mode.Offline)
|
||||
self.subscribeForNotifications()
|
||||
}
|
||||
|
||||
deinit {
|
||||
// self.unsubscribeFromNotifications()
|
||||
self.unsubscribeFromNotifications()
|
||||
}
|
||||
|
||||
// MARK: - Setups
|
||||
|
||||
private func setupModeLabel() {
|
||||
// FIXME: - network availability
|
||||
//if (APIManager.sharedManager.networkAvailable) {
|
||||
if !BatteryManager.sharedManager.batterySaving {
|
||||
modeLabel.text = NSLocalizedString("Online", comment: "")
|
||||
} else {
|
||||
modeLabel.text = NSLocalizedString("Battery Saving", comment: "")
|
||||
}
|
||||
//} else {
|
||||
// modeLabel.text = NSLocalizedString("Offline", comment: "")
|
||||
//}
|
||||
// FIXME: - Show "API Error" in red in case of response errors
|
||||
private func setupModeLabel(mode: RegattaController.Mode) {
|
||||
modeLabel.text = mode.description
|
||||
}
|
||||
|
||||
// MARK: - Notifications
|
||||
|
||||
// FIXME: - Network availability
|
||||
// private func subscribeForNotifications() {
|
||||
// NSNotificationCenter.defaultCenter().addObserver(self,
|
||||
// selector:#selector(networkAvailabilityChanged),
|
||||
// name:APIManager.NotificationType.networkAvailabilityChanged,
|
||||
// object: nil)
|
||||
// }
|
||||
//
|
||||
// private func unsubscribeFromNotifications() {
|
||||
// NSNotificationCenter.defaultCenter().removeObserver(self)
|
||||
// }
|
||||
//
|
||||
// func networkAvailabilityChanged(notification: NSNotification) {
|
||||
// dispatch_async(dispatch_get_main_queue(), {
|
||||
// self.setupModeLabel()
|
||||
// })
|
||||
// }
|
||||
private func subscribeForNotifications() {
|
||||
NSNotificationCenter.defaultCenter().addObserver(self,
|
||||
selector:#selector(regattaControllerModeChanged),
|
||||
name:RegattaController.NotificationType.ModeChanged,
|
||||
object: nil
|
||||
)
|
||||
}
|
||||
|
||||
private func unsubscribeFromNotifications() {
|
||||
NSNotificationCenter.defaultCenter().removeObserver(self)
|
||||
}
|
||||
|
||||
func regattaControllerModeChanged(notification: NSNotification) {
|
||||
dispatch_async(dispatch_get_main_queue(), {
|
||||
guard let mode = notification.userInfo?[RegattaController.UserInfo.Mode] as? RegattaController.Mode else { return }
|
||||
self.setupModeLabel(mode)
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
@@ -12,6 +12,12 @@ import CoreData
|
||||
@objc(Regatta)
|
||||
class Regatta: NSManagedObject {
|
||||
|
||||
func updateWirhRegattaData(regattaData: RegattaData) {
|
||||
serverURL = regattaData.serverURL
|
||||
teamImageURL = regattaData.teamImageURL
|
||||
teamImageRetry = false
|
||||
}
|
||||
|
||||
func eventURL() -> NSURL? {
|
||||
return NSURL(string: "\(serverURL)/gwt/Home.html?navigationTab=Regattas#EventPlace:eventId=\(event.eventID)")
|
||||
}
|
||||
|
||||
@@ -0,0 +1,202 @@
|
||||
//
|
||||
// RegattaController.swift
|
||||
// SAPTracker
|
||||
//
|
||||
// Created by Raimund Wege on 05.07.16.
|
||||
// Copyright © 2016 com.sap.sailing. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
@objc protocol RegattaControllerDelegate {
|
||||
|
||||
func showRegattaAlert(regattaController: RegattaController, alertController: UIAlertController)
|
||||
|
||||
optional func regattaControllerDidUpdate(regattaController: RegattaController)
|
||||
|
||||
// optional func checkInDidStart(checkInController: CheckInController)
|
||||
// optional func checkInDidEnd(checkInController: CheckInController, withSuccess succeed: Bool)
|
||||
|
||||
}
|
||||
|
||||
class RegattaController: NSObject {
|
||||
|
||||
struct NotificationType {
|
||||
static let ModeChanged = "RegattaController.ModeChanged"
|
||||
}
|
||||
|
||||
struct UserInfo {
|
||||
static let Mode = "Mode"
|
||||
}
|
||||
|
||||
enum Mode: String {
|
||||
case BatterySaving = "Battery Saving"
|
||||
case Error = "Error"
|
||||
case Online = "Online"
|
||||
case Offline = "Offline"
|
||||
var description: String {
|
||||
switch self {
|
||||
case .BatterySaving: return NSLocalizedString("Battery Saving", comment: "")
|
||||
case .Error: return NSLocalizedString("Error", comment: "")
|
||||
case .Offline: return NSLocalizedString("Offline", comment: "")
|
||||
case .Online: return NSLocalizedString("Online", comment: "")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private struct SendingInterval {
|
||||
static let Normal: NSTimeInterval = 3
|
||||
static let BatterySaving: NSTimeInterval = 30
|
||||
}
|
||||
|
||||
let regatta: Regatta
|
||||
|
||||
var delegate: RegattaControllerDelegate?
|
||||
|
||||
private (set) var isTracking: Bool = false
|
||||
|
||||
init(regatta: Regatta) {
|
||||
self.regatta = regatta
|
||||
super.init()
|
||||
}
|
||||
|
||||
// MARK: - Notifications
|
||||
|
||||
private func subscribeForNotifications() {
|
||||
NSNotificationCenter.defaultCenter().addObserver(self,
|
||||
selector:#selector(locationManagerUpdated(_:)),
|
||||
name:LocationManager.NotificationType.Updated,
|
||||
object: nil
|
||||
)
|
||||
}
|
||||
|
||||
private func unsubscribeFromNotifications() {
|
||||
NSNotificationCenter.defaultCenter().removeObserver(self)
|
||||
}
|
||||
|
||||
func locationManagerUpdated(notification: NSNotification) {
|
||||
dispatch_async(dispatch_get_main_queue(), {
|
||||
guard self.isTracking else { return }
|
||||
guard let locationData = notification.userInfo?[LocationManager.UserInfo.LocationData] as? LocationData else { return }
|
||||
guard locationData.isValid else { return }
|
||||
let gpsFix = CoreDataManager.sharedManager.newGPSFix(self.regatta)
|
||||
gpsFix.updateWithLocationData(locationData)
|
||||
CoreDataManager.sharedManager.saveContext()
|
||||
})
|
||||
}
|
||||
|
||||
// MARK: - Update
|
||||
|
||||
func update() {
|
||||
SVProgressHUD.show()
|
||||
let regattaData = RegattaData(serverURL: regatta.serverURL,
|
||||
eventID: regatta.event.eventID,
|
||||
leaderboardName: regatta.leaderboard.name,
|
||||
competitorID: regatta.competitor.competitorID
|
||||
)
|
||||
requestManager.getRegattaData(regattaData,
|
||||
success: { (regattaData) in self.updateSuccess(regattaData) },
|
||||
failure: { (title, error) in self.updateFailure() }
|
||||
)
|
||||
}
|
||||
|
||||
func updateSuccess(regattaData: RegattaData) {
|
||||
regatta.event.updateWithEventData(regattaData.eventData)
|
||||
regatta.leaderboard.updateWithLeaderboardData(regattaData.leaderboardData)
|
||||
regatta.competitor.updateWithCompetitorData(regattaData.competitorData)
|
||||
CoreDataManager.sharedManager.saveContext()
|
||||
SVProgressHUD.popActivity()
|
||||
updateFinished()
|
||||
}
|
||||
|
||||
func updateFailure() {
|
||||
updateFinished()
|
||||
}
|
||||
|
||||
func updateFinished() {
|
||||
SVProgressHUD.popActivity()
|
||||
}
|
||||
|
||||
// MARK: - Methods
|
||||
|
||||
func startTracking() -> Bool {
|
||||
isTracking = false
|
||||
do {
|
||||
try LocationManager.sharedManager.startTracking()
|
||||
isTracking = true
|
||||
} catch let error as LocationManager.LocationManagerError {
|
||||
let alertController = UIAlertController(title: error.description, message: nil, preferredStyle: .Alert)
|
||||
let cancelTitle = NSLocalizedString("Cancel", comment: "")
|
||||
let cancelAction = UIAlertAction(title: cancelTitle, style: .Cancel, handler: nil)
|
||||
alertController.addAction(cancelAction)
|
||||
delegate?.showRegattaAlert(self, alertController: alertController)
|
||||
} catch {
|
||||
print("Unknown error")
|
||||
}
|
||||
|
||||
|
||||
isTracking = true
|
||||
sendGPSFixes()
|
||||
return isTracking
|
||||
}
|
||||
|
||||
func stopTracking() {
|
||||
isTracking = false
|
||||
}
|
||||
|
||||
func sendGPSFixes() {
|
||||
var gpsFixes = [GPSFix]()
|
||||
if regatta.gpsFixes != nil {
|
||||
regatta.gpsFixes!.forEach { (gpsFix) in gpsFixes.append(gpsFix as! GPSFix) }
|
||||
}
|
||||
if gpsFixes.count > 0 {
|
||||
print("\(gpsFixes.count) GPS fixes will be sent")
|
||||
requestManager.postGPSFixes(gpsFixes,
|
||||
success: { (operation, responseObject) in self.sendGPSFixesSuccess(gpsFixes) },
|
||||
failure: { (operation, error) in self.sendGPSFixesFailure(error) })
|
||||
} else {
|
||||
print("No GPS fixes available")
|
||||
sendGPSFixesFinished()
|
||||
}
|
||||
}
|
||||
|
||||
private func sendGPSFixesSuccess(gpsFixes: [GPSFix]!) {
|
||||
print(NSThread.isMainThread)
|
||||
dispatch_async(dispatch_get_main_queue(), {
|
||||
print("sending \(gpsFixes.count) GPS fixes was successful")
|
||||
CoreDataManager.sharedManager.deleteGPSFixes(gpsFixes)
|
||||
CoreDataManager.sharedManager.saveContext()
|
||||
self.sendGPSFixesFinished()
|
||||
})
|
||||
}
|
||||
|
||||
private func sendGPSFixesFailure(error: AnyObject) {
|
||||
print(NSThread.isMainThread)
|
||||
dispatch_async(dispatch_get_main_queue(), {
|
||||
print("sending GPS fixes failed for reason: \(error)")
|
||||
self.sendGPSFixesFinished()
|
||||
})
|
||||
}
|
||||
|
||||
private func sendGPSFixesFinished() {
|
||||
if isTracking {
|
||||
let delay = sendingPeriod
|
||||
print("sending next GPS fixes in \(delay) seconds")
|
||||
performSelector(#selector(RegattaController.sendGPSFixes), withObject: nil, afterDelay: delay)
|
||||
} else {
|
||||
print("sending GPS fixes stopped")
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Helper
|
||||
|
||||
var sendingPeriod: NSTimeInterval { get { return BatteryManager.sharedManager.batterySaving ? SendingInterval.BatterySaving : SendingInterval.Normal } }
|
||||
|
||||
// MARK: - Properties
|
||||
|
||||
lazy var requestManager: RequestManager = {
|
||||
let requestManager = RequestManager(baseURLString: self.regatta.serverURL)
|
||||
return requestManager
|
||||
}()
|
||||
|
||||
}
|
||||
+46
-14
@@ -1,5 +1,5 @@
|
||||
//
|
||||
// CheckInData.swift
|
||||
// RegattaData.swift
|
||||
// SAPTracker
|
||||
//
|
||||
// Created by Raimund Wege on 25.05.16.
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
import Foundation
|
||||
|
||||
public class CheckInData: NSObject {
|
||||
public class RegattaData: NSObject {
|
||||
|
||||
private struct ItemNames {
|
||||
static let EventID = "event_id"
|
||||
@@ -16,15 +16,28 @@ public class CheckInData: NSObject {
|
||||
static let CompetitorID = "competitor_id"
|
||||
}
|
||||
|
||||
public let serverURL: String
|
||||
public let eventID: String
|
||||
public let leaderboardName: String
|
||||
public let competitorID: String
|
||||
let serverURL: String
|
||||
let eventID: String
|
||||
let leaderboardName: String
|
||||
let competitorID: String
|
||||
|
||||
init(serverURL: String = "",
|
||||
eventID: String = "",
|
||||
leaderboardName: String = "",
|
||||
competitorID: String = "")
|
||||
var eventData = EventData()
|
||||
var leaderboardData = LeaderboardData()
|
||||
var competitorData = CompetitorData()
|
||||
var teamImageURL: String?
|
||||
|
||||
override init() {
|
||||
serverURL = ""
|
||||
eventID = ""
|
||||
leaderboardName = ""
|
||||
competitorID = ""
|
||||
super.init()
|
||||
}
|
||||
|
||||
init(serverURL: String,
|
||||
eventID: String,
|
||||
leaderboardName: String,
|
||||
competitorID: String)
|
||||
{
|
||||
self.serverURL = serverURL
|
||||
self.eventID = eventID
|
||||
@@ -33,6 +46,14 @@ public class CheckInData: NSObject {
|
||||
super.init()
|
||||
}
|
||||
|
||||
init(regatta: Regatta) {
|
||||
serverURL = regatta.serverURL
|
||||
eventID = regatta.event.eventID
|
||||
competitorID = regatta.competitor.competitorID
|
||||
leaderboardName = regatta.leaderboard.name
|
||||
super.init()
|
||||
}
|
||||
|
||||
convenience init?(url: NSURL) {
|
||||
guard let host = url.host else { return nil }
|
||||
guard let components = NSURLComponents(string: url.absoluteString) else { return nil }
|
||||
@@ -45,9 +66,9 @@ public class CheckInData: NSObject {
|
||||
let queryItems = components.queryItems
|
||||
|
||||
// Get check-in items
|
||||
guard let eventID = CheckInData.queryItemValue(queryItems, itemName: CheckInData.ItemNames.EventID) else { return nil }
|
||||
guard let leaderboardName = CheckInData.queryItemValue(queryItems, itemName: CheckInData.ItemNames.LeaderboardName) else { return nil }
|
||||
guard let competitorID = CheckInData.queryItemValue(queryItems, itemName: CheckInData.ItemNames.CompetitorID) else { return nil }
|
||||
guard let eventID = RegattaData.queryItemValue(queryItems, itemName: ItemNames.EventID) else { return nil }
|
||||
guard let leaderboardName = RegattaData.queryItemValue(queryItems, itemName: ItemNames.LeaderboardName) else { return nil }
|
||||
guard let competitorID = RegattaData.queryItemValue(queryItems, itemName: ItemNames.CompetitorID) else { return nil }
|
||||
|
||||
// Init with values
|
||||
self.init(serverURL: serverURL,
|
||||
@@ -63,9 +84,20 @@ public class CheckInData: NSObject {
|
||||
self.init(url: url)
|
||||
}
|
||||
|
||||
// Properties
|
||||
|
||||
var welcomeString: String {
|
||||
get {
|
||||
return String(format:NSLocalizedString("Hello %@. Welcome to %@. You are registered as %@.", comment: ""),
|
||||
competitorData.name,
|
||||
leaderboardData.name,
|
||||
competitorData.sailID)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Helper
|
||||
|
||||
private class func queryItemValue(queryItems: [NSURLQueryItem]?, itemName: String) -> String? {
|
||||
class private func queryItemValue(queryItems: [NSURLQueryItem]?, itemName: String) -> String? {
|
||||
return queryItems?.filter({(item) -> Bool in item.name == itemName}).first?.value
|
||||
}
|
||||
|
||||
@@ -7,8 +7,6 @@
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import CoreLocation
|
||||
import Darwin
|
||||
|
||||
class RegattaViewController : UIViewController, UINavigationControllerDelegate {
|
||||
|
||||
@@ -51,6 +49,9 @@ class RegattaViewController : UIViewController, UINavigationControllerDelegate {
|
||||
setupNavigationBar()
|
||||
setupImageSourceTypes()
|
||||
setupTeamImage()
|
||||
|
||||
// Test
|
||||
regattaController.update()
|
||||
}
|
||||
|
||||
// MARK: - Setups
|
||||
@@ -73,7 +74,8 @@ class RegattaViewController : UIViewController, UINavigationControllerDelegate {
|
||||
target: self,
|
||||
selector: #selector(RegattaViewController.refreshCountdown),
|
||||
userInfo: nil,
|
||||
repeats: true)
|
||||
repeats: true
|
||||
)
|
||||
refreshCountdown()
|
||||
}
|
||||
|
||||
@@ -185,6 +187,9 @@ class RegattaViewController : UIViewController, UINavigationControllerDelegate {
|
||||
|
||||
@IBAction func showMenuActionSheet(sender: AnyObject) {
|
||||
let alertController = UIAlertController(title: nil, message: nil, preferredStyle: .ActionSheet)
|
||||
if let popoverController = alertController.popoverPresentationController {
|
||||
popoverController.barButtonItem = sender as? UIBarButtonItem
|
||||
}
|
||||
let checkOutTitle = NSLocalizedString("Check-Out", comment: "")
|
||||
let checkOutAction = UIAlertAction(title: checkOutTitle, style: .Default) { (action) in
|
||||
self.showCheckOutAlertController()
|
||||
@@ -207,21 +212,35 @@ class RegattaViewController : UIViewController, UINavigationControllerDelegate {
|
||||
}
|
||||
|
||||
@IBAction func startTrackingButtonTapped(sender: AnyObject) {
|
||||
do {
|
||||
try LocationManager.sharedManager.startTracking()
|
||||
if regattaController.startTracking() {
|
||||
performSegueWithIdentifier("Tracking", sender: sender)
|
||||
} catch let error as LocationManager.LocationManagerError {
|
||||
let alertController = UIAlertController(title: error.description, message: nil, preferredStyle: .Alert)
|
||||
let cancelTitle = NSLocalizedString("Cancel", comment: "")
|
||||
let cancelAction = UIAlertAction(title: cancelTitle, style: .Cancel, handler: nil)
|
||||
alertController.addAction(cancelAction)
|
||||
presentViewController(alertController, animated: true, completion: nil)
|
||||
} catch {
|
||||
print("Unknown error")
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Image picker
|
||||
// MARK: - Alerts
|
||||
|
||||
private func showCheckOutAlertController() {
|
||||
let alertTitle = NSLocalizedString("Check-out of Regatta?", comment: "")
|
||||
let alertController = UIAlertController(title: alertTitle, message: nil, preferredStyle: .Alert)
|
||||
let okTitle = NSLocalizedString("OK", comment: "")
|
||||
let okAction = UIAlertAction(title: okTitle, style: .Default) { (action) in self.preformCheckOut() }
|
||||
let cancelTitle = NSLocalizedString("Cancel", comment: "")
|
||||
let cancelAction = UIAlertAction(title: cancelTitle, style: .Cancel, handler: nil)
|
||||
alertController.addAction(okAction)
|
||||
alertController.addAction(cancelAction)
|
||||
presentViewController(alertController, animated: true, completion: nil)
|
||||
}
|
||||
|
||||
private func preformCheckOut() {
|
||||
requestManager.postCheckOut(regatta.leaderboard.name,
|
||||
competitorId: regatta.competitor.competitorID,
|
||||
success: { (operation, responseObject) in },
|
||||
failure: { (operation, error) in
|
||||
})
|
||||
CoreDataManager.sharedManager.deleteRegatta(regatta)
|
||||
CoreDataManager.sharedManager.saveContext()
|
||||
navigationController!.popViewControllerAnimated(true)
|
||||
}
|
||||
|
||||
func showImageAlertController() {
|
||||
if sourceTypes.count == 1 {
|
||||
@@ -245,41 +264,22 @@ class RegattaViewController : UIViewController, UINavigationControllerDelegate {
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Check-out
|
||||
|
||||
func showCheckOutAlertController() {
|
||||
let alertTitle = NSLocalizedString("Check-out of Regatta?", comment: "")
|
||||
let alertController = UIAlertController(title: alertTitle, message: nil, preferredStyle: .Alert)
|
||||
let okTitle = NSLocalizedString("OK", comment: "")
|
||||
let okAction = UIAlertAction(title: okTitle, style: .Default) { (action) in self.preformCheckOut() }
|
||||
let cancelTitle = NSLocalizedString("Cancel", comment: "")
|
||||
let cancelAction = UIAlertAction(title: cancelTitle, style: .Cancel, handler: nil)
|
||||
alertController.addAction(okAction)
|
||||
alertController.addAction(cancelAction)
|
||||
presentViewController(alertController, animated: true, completion: nil)
|
||||
}
|
||||
|
||||
func preformCheckOut() {
|
||||
requestManager.postCheckOut(regatta.leaderboard.name,
|
||||
competitorId: regatta.competitor.competitorID,
|
||||
success: { (operation, responseObject) in },
|
||||
failure: { (operation, error) in
|
||||
})
|
||||
CoreDataManager.sharedManager.deleteRegatta(regatta!)
|
||||
CoreDataManager.sharedManager.saveContext()
|
||||
navigationController!.popViewControllerAnimated(true)
|
||||
}
|
||||
|
||||
// MARK: - Segue
|
||||
|
||||
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
|
||||
if (segue.identifier == "Tracking") {
|
||||
let nc = segue.destinationViewController as! UINavigationController
|
||||
let vc = nc.viewControllers[0] as! TrackingViewController
|
||||
vc.regatta = regatta
|
||||
let trackingNC = segue.destinationViewController as! UINavigationController
|
||||
let trackingVC = trackingNC.viewControllers[0] as! TrackingViewController
|
||||
trackingVC.regatta = regatta
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Properties
|
||||
|
||||
lazy var regattaController: RegattaController = {
|
||||
return RegattaController(regatta: self.regatta)
|
||||
}()
|
||||
|
||||
}
|
||||
|
||||
// MARK: - UIImagePickerControllerDelegate
|
||||
@@ -345,3 +345,13 @@ extension RegattaViewController: UIImagePickerControllerDelegate {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// MARK: - RegattaControllerDelegate
|
||||
|
||||
extension RegattaViewController: RegattaControllerDelegate {
|
||||
|
||||
func showRegattaAlert(regattaController: RegattaController, alertController: UIAlertController) {
|
||||
presentViewController(alertController, animated: true, completion: nil)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -50,37 +50,142 @@ class RequestManager: NSObject {
|
||||
super.init()
|
||||
}
|
||||
|
||||
// MARK: - Regatta
|
||||
|
||||
func getRegattaData(regattaData: RegattaData,
|
||||
success: (RegattaData) -> Void,
|
||||
failure: (String, NSError) -> Void)
|
||||
{
|
||||
getEventData(regattaData, success: success, failure: failure)
|
||||
}
|
||||
|
||||
func getEventData(regattaData: RegattaData,
|
||||
success: (RegattaData) -> Void,
|
||||
failure: (String, NSError) -> Void)
|
||||
{
|
||||
getEvent(regattaData.eventID,
|
||||
success: { (data) in self.getEventDataSuccess(data, regattaData: regattaData, success: success, failure: failure) },
|
||||
failure: { (title, error) in failure(title, error) }
|
||||
)
|
||||
}
|
||||
|
||||
func getEventDataSuccess(eventData: EventData,
|
||||
regattaData: RegattaData,
|
||||
success: (RegattaData) -> Void,
|
||||
failure: (String, NSError) -> Void)
|
||||
{
|
||||
regattaData.eventData = eventData
|
||||
getLeaderboardData(regattaData, success: success, failure: failure)
|
||||
}
|
||||
|
||||
func getLeaderboardData(regattaData: RegattaData,
|
||||
success: (RegattaData) -> Void,
|
||||
failure: (String, NSError) -> Void)
|
||||
{
|
||||
getLeaderboard(regattaData.leaderboardName,
|
||||
success: { (data) in self.getLeaderboardDataSuccess(data, regattaData: regattaData, success: success, failure: failure) },
|
||||
failure: { (title, error) in failure(title, error) }
|
||||
)
|
||||
}
|
||||
|
||||
func getLeaderboardDataSuccess(leaderboardData: LeaderboardData,
|
||||
regattaData: RegattaData,
|
||||
success: (RegattaData) -> Void,
|
||||
failure: (String, NSError) -> Void)
|
||||
{
|
||||
regattaData.leaderboardData = leaderboardData
|
||||
getCompetitorData(regattaData, success: success, failure: failure)
|
||||
}
|
||||
|
||||
func getCompetitorData(regattaData: RegattaData,
|
||||
success: (RegattaData) -> Void,
|
||||
failure: (String, NSError) -> Void)
|
||||
{
|
||||
getCompetitor(regattaData.competitorID,
|
||||
success: { (data) in self.getCompetitorDataSuccess(data, regattaData: regattaData, success: success, failure: failure) },
|
||||
failure: { (title, error) in failure(title, error) }
|
||||
)
|
||||
}
|
||||
|
||||
func getCompetitorDataSuccess(competitorData: CompetitorData,
|
||||
regattaData: RegattaData,
|
||||
success: (RegattaData) -> Void,
|
||||
failure: (String, NSError) -> Void)
|
||||
{
|
||||
regattaData.competitorData = competitorData
|
||||
getTeamImageURL(regattaData.competitorID, result: { (imageURL) in
|
||||
regattaData.teamImageURL = imageURL
|
||||
success(regattaData)
|
||||
})
|
||||
}
|
||||
|
||||
// MARK: - Event
|
||||
|
||||
func getEvent(eventID: String!,
|
||||
success: (AFHTTPRequestOperation!, AnyObject!) -> Void,
|
||||
failure: (AFHTTPRequestOperation!, AnyObject!) -> Void)
|
||||
func getEvent(eventID: String,
|
||||
success: (EventData) -> Void,
|
||||
failure: (String, NSError) -> Void)
|
||||
{
|
||||
let encodedEventID = eventID.stringByAddingPercentEncodingWithAllowedCharacters(NSCharacterSet.URLPathAllowedCharacterSet()) ?? ""
|
||||
let encodedEventID = eventID.stringByAddingPercentEncodingWithAllowedCharacters(.URLPathAllowedCharacterSet()) ?? ""
|
||||
let urlString = "\(basePathString)/events/\(encodedEventID)"
|
||||
manager.GET(urlString, parameters: nil, success: success, failure: failure)
|
||||
manager.GET(urlString,
|
||||
parameters: nil,
|
||||
success: { (requestOperation, responseObject) in self.getEventSuccess(responseObject, success: success) },
|
||||
failure: { (requestOperation, error) in self.getEventFailure(eventID, error: error, failure: failure) }
|
||||
)
|
||||
}
|
||||
|
||||
func getEventSuccess(responseObject: AnyObject, success: (EventData) -> Void) {
|
||||
success(EventData(dictionary: responseObject as? [String: AnyObject]))
|
||||
}
|
||||
|
||||
func getEventFailure(eventID: String, error: NSError, failure: (String, NSError) -> Void) -> Void {
|
||||
failure(String(format: NSLocalizedString("Couldn't get event %@", comment: ""), eventID), error)
|
||||
}
|
||||
|
||||
// MARK: - Leaderboard
|
||||
|
||||
func getLeaderboard(leaderboardName: String!,
|
||||
success: (AFHTTPRequestOperation!, AnyObject!) -> Void,
|
||||
failure: (AFHTTPRequestOperation!, AnyObject!) -> Void)
|
||||
func getLeaderboard(leaderboardName: String,
|
||||
success: (LeaderboardData) -> Void,
|
||||
failure: (String, NSError) -> Void)
|
||||
{
|
||||
let encodedLeaderboardName = leaderboardName.stringByAddingPercentEncodingWithAllowedCharacters(NSCharacterSet.URLPathAllowedCharacterSet()) ?? ""
|
||||
let encodedLeaderboardName = leaderboardName.stringByAddingPercentEncodingWithAllowedCharacters(.URLPathAllowedCharacterSet()) ?? ""
|
||||
let urlString = "\(basePathString)/leaderboards/\(encodedLeaderboardName)"
|
||||
manager.GET(urlString, parameters: nil, success: success, failure: failure)
|
||||
manager.GET(urlString,
|
||||
parameters: nil,
|
||||
success: { (requestOperation, responseObject) in self.getLeaderboardSuccess(responseObject, success: success) },
|
||||
failure: { (requestOperation, error) in self.getLeaderboardFailure(leaderboardName, error: error, failure: failure) }
|
||||
)
|
||||
}
|
||||
|
||||
func getLeaderboardSuccess(responseObject: AnyObject, success: (LeaderboardData) -> Void) {
|
||||
success(LeaderboardData(dictionary: responseObject as? [String: AnyObject]))
|
||||
}
|
||||
|
||||
func getLeaderboardFailure(leaderboardName: String, error: NSError, failure: (String, NSError) -> Void) {
|
||||
failure(String(format: NSLocalizedString("Couldn't get leader board %@", comment: ""), leaderboardName), error)
|
||||
}
|
||||
|
||||
// MARK: - Competitor
|
||||
|
||||
func getCompetitor(competitorID: String!,
|
||||
success: (AFHTTPRequestOperation!, AnyObject!) -> Void,
|
||||
failure: (AFHTTPRequestOperation!, AnyObject!) -> Void)
|
||||
func getCompetitor(competitorID: String,
|
||||
success: (CompetitorData) -> Void,
|
||||
failure: (String, NSError) -> Void)
|
||||
{
|
||||
let encodedCompetitorID = competitorID.stringByAddingPercentEncodingWithAllowedCharacters(NSCharacterSet.URLPathAllowedCharacterSet()) ?? ""
|
||||
let urlString = "\(basePathString)/competitors/\(encodedCompetitorID)"
|
||||
manager.GET(urlString, parameters: nil, success: success, failure: failure)
|
||||
manager.GET(urlString,
|
||||
parameters: nil,
|
||||
success: { (requestOperation, responseObject) in self.getCompetitorSuccess(responseObject, success: success) },
|
||||
failure: { (requestOperation, error) in self.getCompetitorFailure(competitorID, error: error, failure: failure) }
|
||||
)
|
||||
}
|
||||
|
||||
func getCompetitorSuccess(responseObject: AnyObject, success: (CompetitorData) -> Void) {
|
||||
success(CompetitorData(dictionary: responseObject as? [String: AnyObject]))
|
||||
}
|
||||
|
||||
func getCompetitorFailure(competitorID: String, error: NSError, failure: (String, NSError) -> Void) {
|
||||
failure(String(format: NSLocalizedString("Couldn't get competitor %@", comment: ""), competitorID), error)
|
||||
}
|
||||
|
||||
// MARK: - Team
|
||||
|
||||
@@ -14,15 +14,12 @@ class ScanViewController: UIViewController {
|
||||
@IBOutlet weak var previewView: UIView!
|
||||
@IBOutlet weak var targetImageView: UIImageView!
|
||||
|
||||
private let checkInController = CheckInController()
|
||||
|
||||
private var session: AVCaptureSession!
|
||||
private var output: AVCaptureMetadataOutput!
|
||||
private var previewLayer: AVCaptureVideoPreviewLayer!
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
setupCheckInController()
|
||||
setupSession()
|
||||
}
|
||||
|
||||
@@ -31,12 +28,20 @@ class ScanViewController: UIViewController {
|
||||
startScanning()
|
||||
}
|
||||
|
||||
// MARK: - Setups
|
||||
|
||||
private func setupCheckInController() {
|
||||
checkInController.delegate = self
|
||||
override func viewDidLayoutSubviews() {
|
||||
super.viewDidLayoutSubviews()
|
||||
layoutPreviewLayer()
|
||||
}
|
||||
|
||||
// MARK: - Layouts
|
||||
|
||||
private func layoutPreviewLayer() {
|
||||
previewLayer.frame = previewView.bounds
|
||||
previewLayer.position = CGPointMake(CGRectGetMidX(previewView.bounds), CGRectGetMidY(previewView.bounds))
|
||||
}
|
||||
|
||||
// MARK: - Setups
|
||||
|
||||
private func setupSession() {
|
||||
session = AVCaptureSession()
|
||||
output = AVCaptureMetadataOutput()
|
||||
@@ -54,6 +59,7 @@ class ScanViewController: UIViewController {
|
||||
output.metadataObjectTypes = [AVMetadataObjectTypeQRCode]
|
||||
previewLayer = AVCaptureVideoPreviewLayer(session: self.session)
|
||||
previewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill
|
||||
previewLayer.connection.videoOrientation = videoOrientation(forInterfaceOrientation: UIApplication.sharedApplication().statusBarOrientation)
|
||||
previewLayer.frame = previewView.bounds
|
||||
previewLayer.position = CGPointMake(CGRectGetMidX(previewView.bounds), CGRectGetMidY(previewView.bounds))
|
||||
previewView.layer.addSublayer(previewLayer)
|
||||
@@ -65,13 +71,7 @@ class ScanViewController: UIViewController {
|
||||
// MARK: - UIViewControllerDelegate
|
||||
|
||||
override func willRotateToInterfaceOrientation(toInterfaceOrientation: UIInterfaceOrientation, duration: NSTimeInterval) {
|
||||
if UIDevice.currentDevice().orientation == UIDeviceOrientation.LandscapeLeft {
|
||||
previewLayer!.connection.videoOrientation = AVCaptureVideoOrientation.LandscapeRight
|
||||
} else if UIDevice.currentDevice().orientation == UIDeviceOrientation.LandscapeRight {
|
||||
previewLayer!.connection.videoOrientation = AVCaptureVideoOrientation.LandscapeLeft
|
||||
} else {
|
||||
previewLayer!.connection.videoOrientation = AVCaptureVideoOrientation.Portrait
|
||||
}
|
||||
previewLayer.connection.videoOrientation = videoOrientation(forInterfaceOrientation: toInterfaceOrientation)
|
||||
}
|
||||
|
||||
// MARK: - Scanning
|
||||
@@ -90,6 +90,26 @@ class ScanViewController: UIViewController {
|
||||
targetImageView.image = UIImage(named: "scan_green")
|
||||
}
|
||||
|
||||
// MARK: - Properties
|
||||
|
||||
lazy var checkInController: CheckInController = {
|
||||
let checkInController = CheckInController()
|
||||
checkInController.delegate = self
|
||||
return checkInController
|
||||
}()
|
||||
|
||||
// MARK: - Helper
|
||||
|
||||
private func videoOrientation(forInterfaceOrientation orientation: UIInterfaceOrientation) -> AVCaptureVideoOrientation {
|
||||
switch orientation {
|
||||
case .LandscapeLeft: return .LandscapeLeft
|
||||
case .LandscapeRight: return .LandscapeRight
|
||||
case .Portrait: return .Portrait
|
||||
case .PortraitUpsideDown: return .PortraitUpsideDown
|
||||
case .Unknown: return .Portrait
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// MARK: - CheckInControllerDelegate
|
||||
@@ -120,9 +140,9 @@ extension ScanViewController: AVCaptureMetadataOutputObjectsDelegate {
|
||||
{
|
||||
if metadataObjects.count > 0 {
|
||||
let metadataObject: AVMetadataMachineReadableCodeObject = metadataObjects[0] as! AVMetadataMachineReadableCodeObject
|
||||
if let checkInData = CheckInData(urlString: metadataObject.stringValue) {
|
||||
if let regattaData = RegattaData(urlString: metadataObject.stringValue) {
|
||||
stopScanning()
|
||||
checkInController.startCheckIn(checkInData)
|
||||
checkInController.checkIn(regattaData)
|
||||
} else {
|
||||
let alertTitle = NSLocalizedString("Incorrect QR Code", comment: "")
|
||||
let alertController = UIAlertController(title: alertTitle, message: "", preferredStyle: .Alert)
|
||||
|
||||
@@ -1,129 +0,0 @@
|
||||
//
|
||||
// SendGPSFixesController.swift
|
||||
// SAPTracker
|
||||
//
|
||||
// Created by Raimund Wege on 29.06.16.
|
||||
// Copyright © 2016 com.sap.sailing. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
class SendGPSFixesController: NSObject {
|
||||
|
||||
private struct SendingInterval {
|
||||
static let Normal: NSTimeInterval = 3
|
||||
static let BatterySaving: NSTimeInterval = 30
|
||||
}
|
||||
|
||||
private let regatta: Regatta!
|
||||
private let requestManager: RequestManager!
|
||||
|
||||
private var isRunning: Bool = false
|
||||
|
||||
init(regatta: Regatta) {
|
||||
self.regatta = regatta
|
||||
requestManager = RequestManager(baseURLString: regatta.serverURL)
|
||||
super.init()
|
||||
}
|
||||
|
||||
deinit {
|
||||
unsubscribeFromNotifications()
|
||||
}
|
||||
|
||||
// MARK: - Notifications
|
||||
|
||||
private func subscribeForNotifications() {
|
||||
NSNotificationCenter.defaultCenter().addObserver(self,
|
||||
selector:#selector(locationManagerUpdated(_:)),
|
||||
name:LocationManager.NotificationType.LocationManagerUpdated,
|
||||
object: nil)
|
||||
}
|
||||
|
||||
private func unsubscribeFromNotifications() {
|
||||
NSNotificationCenter.defaultCenter().removeObserver(self)
|
||||
}
|
||||
|
||||
func locationManagerUpdated(notification: NSNotification) {
|
||||
dispatch_async(dispatch_get_main_queue(), {
|
||||
if let userInfo = notification.userInfo {
|
||||
if userInfo[LocationManager.UserInfo.IsValid] as? Bool ?? false {
|
||||
let gpsFix = CoreDataManager.sharedManager.newGPSFix(self.regatta)
|
||||
gpsFix.course = userInfo[LocationManager.UserInfo.Course] as! Double
|
||||
gpsFix.latitude = userInfo[LocationManager.UserInfo.Latitude] as! Double
|
||||
gpsFix.longitude = userInfo[LocationManager.UserInfo.Longitude] as! Double
|
||||
gpsFix.speed = userInfo[LocationManager.UserInfo.Speed] as! Double
|
||||
gpsFix.timestamp = round(userInfo[LocationManager.UserInfo.Timestamp] as! Double * 1000)
|
||||
CoreDataManager.sharedManager.saveContext()
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// MARK: - Methods
|
||||
|
||||
func startSending() {
|
||||
isRunning = true
|
||||
sendGPSFixes()
|
||||
}
|
||||
|
||||
func stopSending() {
|
||||
isRunning = false
|
||||
}
|
||||
|
||||
func sendGPSFixes() {
|
||||
var gpsFixes = [GPSFix]()
|
||||
if regatta.gpsFixes != nil {
|
||||
regatta.gpsFixes!.forEach { (gpsFix) in gpsFixes.append(gpsFix as! GPSFix) }
|
||||
}
|
||||
if gpsFixes.count > 0 {
|
||||
log("\(gpsFixes.count) GPS fixes will be sent")
|
||||
requestManager.postGPSFixes(gpsFixes,
|
||||
success: { (operation, responseObject) in self.sendGPSFixesSuccess(gpsFixes) },
|
||||
failure: { (operation, error) in self.sendGPSFixesFailure(error) })
|
||||
} else {
|
||||
log("No GPS fixes available")
|
||||
sendGPSFixesFinished()
|
||||
}
|
||||
}
|
||||
|
||||
private func sendGPSFixesSuccess(gpsFixes: [GPSFix]!) {
|
||||
print(NSThread.isMainThread)
|
||||
dispatch_async(dispatch_get_main_queue(), {
|
||||
self.log("sending \(gpsFixes.count) GPS fixes was successful")
|
||||
CoreDataManager.sharedManager.deleteGPSFixes(gpsFixes)
|
||||
CoreDataManager.sharedManager.saveContext()
|
||||
self.sendGPSFixesFinished()
|
||||
})
|
||||
}
|
||||
|
||||
private func sendGPSFixesFailure(error: AnyObject) {
|
||||
print(NSThread.isMainThread)
|
||||
dispatch_async(dispatch_get_main_queue(), {
|
||||
self.log("sending GPS fixes failed for reason: \(error)")
|
||||
self.sendGPSFixesFinished()
|
||||
})
|
||||
}
|
||||
|
||||
private func sendGPSFixesFinished() {
|
||||
if isRunning {
|
||||
let delay = sendingPeriod
|
||||
log("sending next GPS fixes in \(delay) seconds")
|
||||
performSelector(#selector(SendGPSFixesController.sendGPSFixes), withObject: nil, afterDelay: delay)
|
||||
} else {
|
||||
log("sending GPS fixes stopped")
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Helper
|
||||
|
||||
private var sendingPeriod: NSTimeInterval {
|
||||
get {
|
||||
return BatteryManager.sharedManager.batterySaving ? SendingInterval.BatterySaving : SendingInterval.Normal
|
||||
}
|
||||
}
|
||||
|
||||
private func log(message: String) {
|
||||
print("[GPSFixesController] \(message)")
|
||||
}
|
||||
|
||||
}
|
||||
@@ -40,8 +40,14 @@ class SpeedViewController: UIViewController {
|
||||
private func subscribeForNotifications() {
|
||||
NSNotificationCenter.defaultCenter().addObserver(self,
|
||||
selector:#selector(locationManagerUpdated(_:)),
|
||||
name:LocationManager.NotificationType.LocationManagerUpdated,
|
||||
object: nil)
|
||||
name:LocationManager.NotificationType.Updated,
|
||||
object: nil
|
||||
)
|
||||
NSNotificationCenter.defaultCenter().addObserver(self,
|
||||
selector:#selector(locationManagerFailed(_:)),
|
||||
name:LocationManager.NotificationType.Failed,
|
||||
object: nil
|
||||
)
|
||||
}
|
||||
|
||||
private func unsubscribeFromNotifications() {
|
||||
@@ -50,7 +56,14 @@ class SpeedViewController: UIViewController {
|
||||
|
||||
func locationManagerUpdated(notification: NSNotification) {
|
||||
dispatch_async(dispatch_get_main_queue(), {
|
||||
self.setupSpeedLabel(notification.userInfo![LocationManager.UserInfo.Speed] as! Double)
|
||||
guard let locationData = notification.userInfo?[LocationManager.UserInfo.LocationData] as? LocationData else { return }
|
||||
self.setupSpeedLabel(locationData.location.speed)
|
||||
})
|
||||
}
|
||||
|
||||
func locationManagerFailed(notification: NSNotification) {
|
||||
dispatch_async(dispatch_get_main_queue(), {
|
||||
self.setupSpeedLabel(-1.0)
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -35,12 +35,14 @@ class StatusTrackingTableViewCell: UITableViewCell {
|
||||
private func subscribeForNotifications() {
|
||||
NSNotificationCenter.defaultCenter().addObserver(self,
|
||||
selector:#selector(locationManagerUpdated(_:)),
|
||||
name:LocationManager.NotificationType.LocationManagerUpdated,
|
||||
object: nil)
|
||||
name:LocationManager.NotificationType.Updated,
|
||||
object: nil
|
||||
)
|
||||
NSNotificationCenter.defaultCenter().addObserver(self,
|
||||
selector:#selector(locationManagerFailed(_:)),
|
||||
name:LocationManager.NotificationType.LocationManagerFailed,
|
||||
object: nil)
|
||||
name:LocationManager.NotificationType.Failed,
|
||||
object: nil
|
||||
)
|
||||
}
|
||||
|
||||
private func unsubscribeFromNotifications() {
|
||||
|
||||
@@ -33,7 +33,8 @@ class TimerViewController: UIViewController {
|
||||
target: self,
|
||||
selector: #selector(tick),
|
||||
userInfo: nil,
|
||||
repeats: true)
|
||||
repeats: true
|
||||
)
|
||||
NSRunLoop.currentRunLoop().addTimer(timer, forMode:NSRunLoopCommonModes)
|
||||
}
|
||||
|
||||
|
||||
@@ -10,7 +10,8 @@ import Foundation
|
||||
|
||||
class TrackingViewController : UIViewController {
|
||||
|
||||
var regatta: Regatta?
|
||||
var regatta: Regatta!
|
||||
var regattaController: RegattaController!
|
||||
|
||||
@IBOutlet weak var tableView: UITableView!
|
||||
@IBOutlet weak var tableViewHeight: NSLayoutConstraint!
|
||||
|
||||
Reference in new issue
Block a user