Skip to content

Commit 21af1b3

Browse files
committed
- Updated README
- Fixed spelling and grammar - Just ask for Health permission every time the app opens or, on iOS 12/watchOS 5 and later, ask HealthKit if permission should be requested
1 parent b0d9fc7 commit 21af1b3

File tree

17 files changed

+52
-107
lines changed

17 files changed

+52
-107
lines changed

Gym Tracker Core/Localizable.strings

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,6 @@
7171
"WORKOUT_SAVED" = "Workout saved";
7272
"WORKOUT_SAVE_ERROR" = "Error saving workout";
7373

74-
"HEALTH_ACCESS_MANAGE" = "You can also manage Health access inside the Health app, Sources tab.";
7574
"REPORT_TEXT" = "Report any problem also on Twitter @piscoTech or at GitHub tapping Source Code.";
7675
"ERR_BACKUP_UNAVAILABLE" = "Login with your iCloud account and enable iCloud Drive for Gym Tracker to use backups.";
7776
"BACKUP_USAGE_MANUAL" = "Manually backup your workouts to your iCloud Drive. You can restore a backup any time, share with your friends or edit directly to customize workouts and exercizes before importing them again.";

Gym Tracker Core/Main iOS & watchOS.swift

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,13 @@
99
import Foundation
1010
import HealthKit
1111

12-
///Keep track of the version of health authorization required, increase this number to automatically display an authorization request.
13-
public let authRequired = 2
14-
///List of health data to require access to.
12+
/// List of health data to require access to.
1513
public let healthReadData = Set([
1614
HKObjectType.workoutType(),
1715
HKObjectType.quantityType(forIdentifier: .heartRate)!,
1816
HKObjectType.quantityType(forIdentifier: .activeEnergyBurned)!
1917
])
20-
///List of health data to require write access to.
18+
/// List of health data to require write access to.
2119
public let healthWriteData = Set([
2220
HKObjectType.workoutType(),
2321
HKObjectType.quantityType(forIdentifier: .activeEnergyBurned)!

Gym Tracker Core/Preferences.swift

Lines changed: 0 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,6 @@ enum PreferenceKeys: String, KeyValueStoreKey {
3232
case secondaryInfoChangeCache = "secondaryInfoChangeCache"
3333
case currentChoices = "currentChoices"
3434

35-
case authorized = "authorized"
36-
case authVersion = "authVersion"
37-
3835
case useBackups = "useBackups"
3936
case lastBackup = "lastBackup"
4037

@@ -362,28 +359,6 @@ public class Preferences {
362359
}
363360
}
364361

365-
// MARK: - Health Access
366-
367-
public var authorized: Bool {
368-
get {
369-
return local.bool(forKey: PreferenceKeys.authorized)
370-
}
371-
set {
372-
local.set(newValue, forKey: PreferenceKeys.authorized)
373-
local.synchronize()
374-
}
375-
}
376-
377-
public var authVersion: Int {
378-
get {
379-
return local.integer(forKey: PreferenceKeys.authVersion)
380-
}
381-
set {
382-
local.set(newValue, forKey: PreferenceKeys.authVersion)
383-
local.synchronize()
384-
}
385-
}
386-
387362
// MARK: - Backups
388363

389364
public var useBackups: Bool {

Gym Tracker iOS/AppDelegate.swift

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -66,10 +66,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
6666
}
6767

6868
dataManager.delegate = self
69-
70-
if !dataManager.preferences.authorized || dataManager.preferences.authVersion < authRequired {
71-
authorizeHealthAccess()
72-
}
69+
authorizeHealthAccess()
7370

7471
if !dataManager.preferences.firstLaunchDone {
7572
dataManager.preferences.firstLaunchDone = true
@@ -206,21 +203,23 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
206203
}
207204

208205
func authorizeHealthAccess() {
209-
healthStore.requestAuthorization(toShare: healthWriteData, read: healthReadData) { success, _ in
210-
if success {
211-
self.dataManager.preferences.authorized = true
212-
self.dataManager.preferences.authVersion = authRequired
206+
let req = {
207+
healthStore.requestAuthorization(toShare: healthWriteData, read: healthReadData) { _, _ in }
208+
}
209+
210+
if #available(iOS 12.0, *) {
211+
healthStore.getRequestStatusForAuthorization(toShare: healthWriteData, read: healthReadData) { status, _ in
212+
if status != .unnecessary {
213+
req()
214+
}
213215
}
216+
} else {
217+
req()
214218
}
215219
}
216220

217221
func applicationShouldRequestHealthAuthorization(_ application: UIApplication) {
218-
healthStore.handleAuthorizationForExtension { success, _ in
219-
if success {
220-
self.dataManager.preferences.authorized = true
221-
self.dataManager.preferences.authVersion = authRequired
222-
}
223-
}
222+
healthStore.handleAuthorizationForExtension { _, _ in }
224223
}
225224

226225
func applicationWillResignActive(_ application: UIApplication) {

Gym Tracker iOS/Base.lproj/Main.storyboard

Lines changed: 4 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -760,29 +760,8 @@
760760
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
761761
<color key="backgroundColor" cocoaTouchSystemColor="groupTableViewBackgroundColor"/>
762762
<prototypes>
763-
<tableViewCell contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" reuseIdentifier="authorize" id="inV-Ge-P6w">
764-
<rect key="frame" x="0.0" y="55.5" width="375" height="44"/>
765-
<autoresizingMask key="autoresizingMask"/>
766-
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="inV-Ge-P6w" id="luH-pe-Wsq">
767-
<rect key="frame" x="0.0" y="0.0" width="375" height="43.5"/>
768-
<autoresizingMask key="autoresizingMask"/>
769-
<subviews>
770-
<button opaque="NO" userInteractionEnabled="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="h0h-jk-BOg">
771-
<rect key="frame" x="16" y="0.0" width="212" height="43.5"/>
772-
<fontDescription key="fontDescription" type="system" pointSize="16"/>
773-
<state key="normal" title="Authorize Health data access"/>
774-
</button>
775-
</subviews>
776-
<constraints>
777-
<constraint firstItem="h0h-jk-BOg" firstAttribute="leading" secondItem="luH-pe-Wsq" secondAttribute="leadingMargin" id="3pY-v1-mDk"/>
778-
<constraint firstItem="h0h-jk-BOg" firstAttribute="top" secondItem="luH-pe-Wsq" secondAttribute="top" id="5Pb-mu-FEo"/>
779-
<constraint firstAttribute="bottom" secondItem="h0h-jk-BOg" secondAttribute="bottom" id="EaW-fC-AAd"/>
780-
<constraint firstAttribute="trailingMargin" relation="greaterThanOrEqual" secondItem="h0h-jk-BOg" secondAttribute="trailingMargin" id="qW9-y7-gJN"/>
781-
</constraints>
782-
</tableViewCellContentView>
783-
</tableViewCell>
784763
<tableViewCell contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" reuseIdentifier="enableBackup" id="qGz-bD-kFg">
785-
<rect key="frame" x="0.0" y="99.5" width="375" height="44"/>
764+
<rect key="frame" x="0.0" y="55.5" width="375" height="44"/>
786765
<autoresizingMask key="autoresizingMask"/>
787766
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="qGz-bD-kFg" id="BcT-hM-Yby">
788767
<rect key="frame" x="0.0" y="0.0" width="375" height="43.5"/>
@@ -812,7 +791,7 @@
812791
</tableViewCellContentView>
813792
</tableViewCell>
814793
<tableViewCell contentMode="scaleToFill" selectionStyle="default" accessoryType="disclosureIndicator" indentationWidth="10" reuseIdentifier="backupList" textLabel="C0f-wB-YJQ" style="IBUITableViewCellStyleDefault" id="haK-UN-tQ1">
815-
<rect key="frame" x="0.0" y="143.5" width="375" height="44"/>
794+
<rect key="frame" x="0.0" y="99.5" width="375" height="44"/>
816795
<autoresizingMask key="autoresizingMask"/>
817796
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="haK-UN-tQ1" id="qIb-8A-EWC">
818797
<rect key="frame" x="0.0" y="0.0" width="341" height="43.5"/>
@@ -832,7 +811,7 @@
832811
</connections>
833812
</tableViewCell>
834813
<tableViewCell contentMode="scaleToFill" selectionStyle="default" accessoryType="disclosureIndicator" indentationWidth="10" reuseIdentifier="sourceCode" textLabel="FTV-hG-Hel" style="IBUITableViewCellStyleDefault" id="iMw-n3-ZfA">
835-
<rect key="frame" x="0.0" y="187.5" width="375" height="44"/>
814+
<rect key="frame" x="0.0" y="143.5" width="375" height="44"/>
836815
<autoresizingMask key="autoresizingMask"/>
837816
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="iMw-n3-ZfA" id="vYu-8g-3ul">
838817
<rect key="frame" x="0.0" y="0.0" width="341" height="43.5"/>
@@ -849,7 +828,7 @@
849828
</tableViewCellContentView>
850829
</tableViewCell>
851830
<tableViewCell contentMode="scaleToFill" selectionStyle="default" accessoryType="disclosureIndicator" indentationWidth="10" reuseIdentifier="contact" textLabel="7Cg-0X-hva" style="IBUITableViewCellStyleDefault" id="240-4O-oPZ">
852-
<rect key="frame" x="0.0" y="231.5" width="375" height="44"/>
831+
<rect key="frame" x="0.0" y="187.5" width="375" height="44"/>
853832
<autoresizingMask key="autoresizingMask"/>
854833
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="240-4O-oPZ" id="TOa-c4-7TT">
855834
<rect key="frame" x="0.0" y="0.0" width="341" height="43.5"/>

Gym Tracker iOS/SettingsVC.swift

Lines changed: 7 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ import GymTrackerCore
1212

1313
class SettingsViewController: UITableViewController {
1414

15-
private var healthInfo: String!
1615
private var appInfo: String!
1716
private var errNoBackup: String!
1817
private var backupUsageManual: String!
@@ -27,7 +26,6 @@ class SettingsViewController: UITableViewController {
2726

2827
appDelegate.settings = self
2928

30-
healthInfo = GTLocalizedString("HEALTH_ACCESS_MANAGE", comment: "Health")
3129
appInfo = GTLocalizedString("REPORT_TEXT", comment: "Report problem") + "\n\nGym Tracker \(Bundle.main.versionDescription)\n© 2017-2018 Marco Boschi"
3230
errNoBackup = GTLocalizedString("ERR_BACKUP_UNAVAILABLE", comment: "Cannot use becuase...")
3331
backupUsageManual = GTLocalizedString("BACKUP_USAGE_MANUAL", comment: "How-to")
@@ -38,24 +36,22 @@ class SettingsViewController: UITableViewController {
3836
appDelegate.dataManager.importExportManager.doBackup()
3937

4038
DispatchQueue.main.async {
41-
self.tableView.reloadSections([1], with: .automatic)
39+
self.tableView.reloadSections([0], with: .automatic)
4240
}
4341
}
4442
}
4543

4644
override func numberOfSections(in tableView: UITableView) -> Int {
47-
return 3
45+
return 2
4846
}
4947

5048
override func tableView(_ tableView: UITableView, titleForFooterInSection section: Int) -> String? {
5149
switch section {
5250
case 0:
53-
return healthInfo
54-
case 1:
5551
return iCloudEnabled ? (
5652
appDelegate.dataManager.preferences.useBackups ? backupUsageAuto : backupUsageManual
5753
) : errNoBackup
58-
case 2:
54+
case 1:
5955
return appInfo
6056
default:
6157
return nil
@@ -65,10 +61,8 @@ class SettingsViewController: UITableViewController {
6561
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
6662
switch section {
6763
case 0:
68-
return 1
69-
case 1:
7064
return iCloudEnabled ? 2 : 1
71-
case 2:
65+
case 1:
7266
return 2
7367
default:
7468
fatalError("Unknown section")
@@ -78,8 +72,6 @@ class SettingsViewController: UITableViewController {
7872
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
7973
switch indexPath.section {
8074
case 0:
81-
return tableView.dequeueReusableCell(withIdentifier: "authorize", for: indexPath)
82-
case 1:
8375
if indexPath.row == 0 {
8476
let cell = tableView.dequeueReusableCell(withIdentifier: "enableBackup", for: indexPath)
8577
let swt = cell.viewWithTag(10) as! UISwitch
@@ -90,7 +82,7 @@ class SettingsViewController: UITableViewController {
9082
} else {
9183
return tableView.dequeueReusableCell(withIdentifier: "backupList", for: indexPath)
9284
}
93-
case 2:
85+
case 1:
9486
return tableView.dequeueReusableCell(withIdentifier: indexPath.row == 0 ? "sourceCode" : "contact", for: indexPath)
9587
default:
9688
fatalError("Unknown section")
@@ -104,9 +96,7 @@ class SettingsViewController: UITableViewController {
10496

10597
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
10698
switch (indexPath.section, indexPath.row) {
107-
case (0, 0):
108-
appDelegate.authorizeHealthAccess()
109-
case (2, 0):
99+
case (1, 0):
110100
UIApplication.shared.open(URL(string: "https://github.com/piscoTech/GymTracker")!)
111101
default:
112102
break
@@ -121,7 +111,7 @@ class SettingsViewController: UITableViewController {
121111
}
122112

123113
appDelegate.dataManager.preferences.useBackups = sender.isOn
124-
tableView.reloadSections([1], with: .automatic)
114+
tableView.reloadSections([0], with: .automatic)
125115
if sender.isOn {
126116
appDelegate.dataManager.importExportManager.doBackup()
127117
}

Gym Tracker watchOS Extension/WorkoutListIC.swift

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -35,10 +35,7 @@ class WorkoutListInterfaceController: WKInterfaceController {
3535
// This method is called when watch view controller is about to be visible to user
3636
super.willActivate()
3737

38-
if !appDelegate.dataManager.preferences.authorized || appDelegate.dataManager.preferences.authVersion < authRequired {
39-
authorize()
40-
}
41-
38+
authorize()
4239
activated = true
4340
}
4441

@@ -88,11 +85,18 @@ class WorkoutListInterfaceController: WKInterfaceController {
8885
}
8986

9087
func authorize() {
91-
healthStore.requestAuthorization(toShare: healthWriteData, read: healthReadData) { (success, _) in
92-
if success {
93-
appDelegate.dataManager.preferences.authorized = true
94-
appDelegate.dataManager.preferences.authVersion = authRequired
88+
let req = {
89+
healthStore.requestAuthorization(toShare: healthWriteData, read: healthReadData) { _, _ in }
90+
}
91+
92+
if #available(watchOS 5.0, *) {
93+
healthStore.getRequestStatusForAuthorization(toShare: healthWriteData, read: healthReadData) { status, _ in
94+
if status != .unnecessary {
95+
req()
96+
}
9597
}
98+
} else {
99+
req()
96100
}
97101
}
98102

Gym Tracker.xcodeproj/project.pbxproj

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1118,7 +1118,7 @@
11181118
isa = PBXProject;
11191119
attributes = {
11201120
LastSwiftUpdateCheck = 1000;
1121-
LastUpgradeCheck = 0940;
1121+
LastUpgradeCheck = 1000;
11221122
ORGANIZATIONNAME = "Marco Boschi";
11231123
TargetAttributes = {
11241124
7A2E10211FBDCC6F004767D7 = {
@@ -1768,7 +1768,7 @@
17681768
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
17691769
CLANG_ENABLE_OBJC_WEAK = YES;
17701770
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
1771-
CODE_SIGN_IDENTITY = "iPhone Developer";
1771+
CODE_SIGN_IDENTITY = "";
17721772
CODE_SIGN_STYLE = Automatic;
17731773
CURRENT_PROJECT_VERSION = 1;
17741774
DEFINES_MODULE = YES;
@@ -1804,7 +1804,7 @@
18041804
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
18051805
CLANG_ENABLE_OBJC_WEAK = YES;
18061806
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
1807-
CODE_SIGN_IDENTITY = "iPhone Developer";
1807+
CODE_SIGN_IDENTITY = "";
18081808
CODE_SIGN_STYLE = Automatic;
18091809
CURRENT_PROJECT_VERSION = 1;
18101810
DEFINES_MODULE = YES;
@@ -1839,7 +1839,7 @@
18391839
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
18401840
CLANG_ENABLE_OBJC_WEAK = YES;
18411841
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
1842-
CODE_SIGN_IDENTITY = "iPhone Developer";
1842+
CODE_SIGN_IDENTITY = "";
18431843
CODE_SIGN_STYLE = Automatic;
18441844
CURRENT_PROJECT_VERSION = 1;
18451845
DEFINES_MODULE = YES;
@@ -1874,7 +1874,7 @@
18741874
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
18751875
CLANG_ENABLE_OBJC_WEAK = YES;
18761876
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
1877-
CODE_SIGN_IDENTITY = "iPhone Developer";
1877+
CODE_SIGN_IDENTITY = "";
18781878
CODE_SIGN_STYLE = Automatic;
18791879
CURRENT_PROJECT_VERSION = 1;
18801880
DEFINES_MODULE = YES;
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.

PRIVACY.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
# Privacy Policy
2-
_Gym Tracker_ access user Health data only for displaying it during a workout and to correctly create a completed workout, any read data is never persisted in any way outside the Health app on the device itself.
2+
_Gym Tracker_ accesses user Health data only for displaying it during a workout and to correctly create a completed workout, any read data is never persisted in any way outside the Health app on the device itself.
33

4-
_Gym Tracker_ access only heart rate, workouts and active energy data after receiving user consent and can function as normal if the user doesn't want to give access to some of these allowing a nice workout experience.
4+
_Gym Tracker_ accesses only heart rate, workouts and active energy data after receiving user consent and can function as normal if the user doesn't want to give access to some of these, allowing a nice workout experience nonetheless.

README.md

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,17 @@ Do you go to the gym and are tired of manually keep track of exercizes, sets and
99

1010
At the end your workout is automatically saved inside the Health app, if you're using an Apple Watch with detailed heart rate and calories.
1111

12-
Backup and restore your workouts using iCloud Drive or export and share them with your friends. Backups and exported workout are in XML format and easily accessible from inside the iCloud Drive folder and app, you can manually edit them and importing them again, before import data is validated against this [XSD grammar](https://github.com/piscoTech/GymTracker/blob/master/Gym%20Tracker%20iOS/workout.xsd).
12+
Backup and restore your workouts using iCloud Drive or export and share them with your friends. Backups and exported workout are in XML format and easily accessible from inside the iCloud Drive folder and app, you can manually edit them and import them again, before import data is validated against this [XSD grammar](https://github.com/piscoTech/GymTracker/blob/master/Gym%20Tracker%20iOS/workout.xsd).
1313

1414
Support me by buying the app on the AppStore<br>
1515
[![Download on the AppStore](http://www.marcoboschi.altervista.org/img/app_store_en.svg)](https://itunes.apple.com/us/app/gym-tracker-gym-workout-tracker/id1224155362?ls=1&mt=8)
1616

1717
## Project Setup
18-
The framework `MBLibrary` referenced by this project is available [here](https://github.com/piscoTech/MBLibrary), version currently in use is [1.2.2](https://github.com/piscoTech/MBLibrary/releases/tag/v1.2.2(9)).
18+
The framework `MBLibrary` referenced by this project is available [here](https://github.com/piscoTech/MBLibrary), version currently in use is [1.3](https://github.com/piscoTech/MBLibrary/releases/tag/v1.3(10)).
1919

2020
## Customization
21-
General behaviour of the app can be configured via global variables in `Main iOS & watchOS.swift`:
22-
23-
* `maxRest`: Max rest period allowed in seconds, make sure it's a multiple of 30s.
24-
* `authRequired`, `healthReadData` and `healthWriteData`: Used to save the latest authorization requested in `UserDefaults`, when `authRequired` is greater than the saved value the user will be promped for authorization upon next launch, increment this value when adding new data to be read or write to `healthReadData` or `healthWriteData`.
21+
General behaviour of the app can be configured via global and static variables:
22+
- File `Main iOS & watchOS.swift`:
23+
* `healthReadData` and `healthWriteData`: The list of data types to be read and written to Health.
24+
- Class `GTRest`:
25+
* `maxRest`: Max rest period allowed in seconds, make sure it's a multiple of 30 seconds, or whatever you set in `restStep`.

0 commit comments

Comments
 (0)