From 3f63c7050b63316b287d6e4ebb61e491ab80d5d5 Mon Sep 17 00:00:00 2001 From: "HY. Kelvin Lee" Date: Mon, 19 Jul 2021 13:09:52 -0700 Subject: [PATCH 1/9] Update project configuration --- README.md | 4 ++-- TermiWatch WatchKit App/Info.plist | 2 +- TermiWatch WatchKit Extension/Info.plist | 2 +- TermiWatch.xcodeproj/project.pbxproj | 22 +++++++++++----------- 4 files changed, 15 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index 2e49be1..4614a1e 100644 --- a/README.md +++ b/README.md @@ -43,7 +43,7 @@ For devices running watchOS 5 or higher. ![Show project and targets list](Screenshots/Show_project_and_targets_list.png) 1. Select the **General** tab: ![Change bundle identifier 1](Screenshots/Change_bundle_identifier1.png) - 1. For each of the 3 **targets** replece *kuglee* in the **Bundle Identifier** field with the name of your developer account. (The name of your Apple ID without the *@xxxx.com*.) + 1. For each of the 3 **targets** replece *k0042n* in the **Bundle Identifier** field with the name of your developer account. (The name of your Apple ID without the *@xxxx.com*.) ![Change bundle identifier 2](Screenshots/Change_bundle_identifier2.png) 1. Change the project's team: 1. Select the **Signing & Capabilities** tab: @@ -52,7 +52,7 @@ For devices running watchOS 5 or higher. ![Change team 2](Screenshots/Change_team2.png) 1. Manually replace bundle identifiers: 1. Select **Xcode** menu -> **Find** -> **Find and Replace in Project…**. - 1. In the **Text** field type *kuglee*. + 1. In the **Text** field type *k0042n*. 1. In the **With** field type the name of your developer account. (The name of your Apple ID without the @xxxx.com.) 1. Click the **Replace All** button. ![Change bundle identifier 3](Screenshots/Change_bundle_identifier3.png) diff --git a/TermiWatch WatchKit App/Info.plist b/TermiWatch WatchKit App/Info.plist index af0cd8c..56e90c1 100644 --- a/TermiWatch WatchKit App/Info.plist +++ b/TermiWatch WatchKit App/Info.plist @@ -26,7 +26,7 @@ UIInterfaceOrientationPortraitUpsideDown WKCompanionAppBundleIdentifier - com.kuglee.TermiWatch + com.k0042n.TermiWatch WKWatchKitApp diff --git a/TermiWatch WatchKit Extension/Info.plist b/TermiWatch WatchKit Extension/Info.plist index b958b89..d89d604 100644 --- a/TermiWatch WatchKit Extension/Info.plist +++ b/TermiWatch WatchKit Extension/Info.plist @@ -25,7 +25,7 @@ NSExtensionAttributes WKAppBundleIdentifier - com.kuglee.TermiWatch.watchkitapp + com.k0042n.TermiWatch.watchkitapp NSExtensionPointIdentifier com.apple.watchkit diff --git a/TermiWatch.xcodeproj/project.pbxproj b/TermiWatch.xcodeproj/project.pbxproj index 659a0f7..5361797 100644 --- a/TermiWatch.xcodeproj/project.pbxproj +++ b/TermiWatch.xcodeproj/project.pbxproj @@ -527,14 +527,14 @@ ASSETCATALOG_COMPILER_COMPLICATION_NAME = Complication; CODE_SIGN_ENTITLEMENTS = "TermiWatch WatchKit Extension/TermiWatch WatchKit Extension.entitlements"; CODE_SIGN_STYLE = Automatic; - DEVELOPMENT_TEAM = C89KNBM28S; + DEVELOPMENT_TEAM = 59BBS8YWDG; INFOPLIST_FILE = "TermiWatch WatchKit Extension/Info.plist"; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", "@executable_path/../../Frameworks", ); - PRODUCT_BUNDLE_IDENTIFIER = com.kuglee.TermiWatch.watchkitapp.watchkitextension; + PRODUCT_BUNDLE_IDENTIFIER = com.k0042n.TermiWatch.watchkitapp.watchkitextension; PRODUCT_NAME = "${TARGET_NAME}"; SDKROOT = watchos; SKIP_INSTALL = YES; @@ -550,14 +550,14 @@ ASSETCATALOG_COMPILER_COMPLICATION_NAME = Complication; CODE_SIGN_ENTITLEMENTS = "TermiWatch WatchKit Extension/TermiWatch WatchKit Extension.entitlements"; CODE_SIGN_STYLE = Automatic; - DEVELOPMENT_TEAM = C89KNBM28S; + DEVELOPMENT_TEAM = 59BBS8YWDG; INFOPLIST_FILE = "TermiWatch WatchKit Extension/Info.plist"; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", "@executable_path/../../Frameworks", ); - PRODUCT_BUNDLE_IDENTIFIER = com.kuglee.TermiWatch.watchkitapp.watchkitextension; + PRODUCT_BUNDLE_IDENTIFIER = com.k0042n.TermiWatch.watchkitapp.watchkitextension; PRODUCT_NAME = "${TARGET_NAME}"; SDKROOT = watchos; SKIP_INSTALL = YES; @@ -573,10 +573,10 @@ ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_STYLE = Automatic; - DEVELOPMENT_TEAM = C89KNBM28S; + DEVELOPMENT_TEAM = 59BBS8YWDG; IBSC_MODULE = TermiWatch_WatchKit_Extension; INFOPLIST_FILE = "TermiWatch WatchKit App/Info.plist"; - PRODUCT_BUNDLE_IDENTIFIER = com.kuglee.TermiWatch.watchkitapp; + PRODUCT_BUNDLE_IDENTIFIER = com.k0042n.TermiWatch.watchkitapp; PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = watchos; SKIP_INSTALL = YES; @@ -592,10 +592,10 @@ ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_STYLE = Automatic; - DEVELOPMENT_TEAM = C89KNBM28S; + DEVELOPMENT_TEAM = 59BBS8YWDG; IBSC_MODULE = TermiWatch_WatchKit_Extension; INFOPLIST_FILE = "TermiWatch WatchKit App/Info.plist"; - PRODUCT_BUNDLE_IDENTIFIER = com.kuglee.TermiWatch.watchkitapp; + PRODUCT_BUNDLE_IDENTIFIER = com.k0042n.TermiWatch.watchkitapp; PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = watchos; SKIP_INSTALL = YES; @@ -611,14 +611,14 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_ENTITLEMENTS = TermiWatch/TermiWatch.entitlements; CODE_SIGN_STYLE = Automatic; - DEVELOPMENT_TEAM = C89KNBM28S; + DEVELOPMENT_TEAM = 59BBS8YWDG; INFOPLIST_FILE = TermiWatch/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 12.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", ); - PRODUCT_BUNDLE_IDENTIFIER = com.kuglee.TermiWatch; + PRODUCT_BUNDLE_IDENTIFIER = com.k0042n.TermiWatch; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; @@ -638,7 +638,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - PRODUCT_BUNDLE_IDENTIFIER = com.kuglee.TermiWatch; + PRODUCT_BUNDLE_IDENTIFIER = com.k0042n.TermiWatch; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; From f1a1dd5a744296f1dd3df1c29f93006bf777ce2e Mon Sep 17 00:00:00 2001 From: "HY. Kelvin Lee" Date: Mon, 19 Jul 2021 16:55:31 -0700 Subject: [PATCH 2/9] Add username and hostname customization --- .../Base.lproj/Interface.storyboard | 13 +- .../InterfaceController.swift | 22 +++ TermiWatch/Base.lproj/LaunchScreen.storyboard | 12 +- TermiWatch/Base.lproj/Main.storyboard | 128 +++++++++++++++++- TermiWatch/ViewController.swift | 56 ++++++++ 5 files changed, 213 insertions(+), 18 deletions(-) diff --git a/TermiWatch WatchKit App/Base.lproj/Interface.storyboard b/TermiWatch WatchKit App/Base.lproj/Interface.storyboard index 0f1f189..6315964 100644 --- a/TermiWatch WatchKit App/Base.lproj/Interface.storyboard +++ b/TermiWatch WatchKit App/Base.lproj/Interface.storyboard @@ -1,12 +1,10 @@ - - - - + + - - + + @@ -263,9 +261,12 @@ + + + diff --git a/TermiWatch WatchKit Extension/InterfaceController.swift b/TermiWatch WatchKit Extension/InterfaceController.swift index 965a64e..67f2446 100644 --- a/TermiWatch WatchKit Extension/InterfaceController.swift +++ b/TermiWatch WatchKit Extension/InterfaceController.swift @@ -5,6 +5,7 @@ import PMKHealthKit import PromiseKit import Swizzle import WatchKit +import WatchConnectivity // MARK: - UIKit stubs @@ -172,14 +173,21 @@ func batteryIndicatorString(percent: UInt) -> String { } class InterfaceController: WKInterfaceController { + @IBOutlet weak var userHostLabelNow: WKInterfaceLabel! @IBOutlet var batteryLabel: WKInterfaceLabel! @IBOutlet var activityLabel: WKInterfaceLabel! @IBOutlet var stepsLabel: WKInterfaceLabel! @IBOutlet var heartRateLabel: WKInterfaceLabel! @IBOutlet var temperatureLabel: WKInterfaceLabel! + @IBOutlet weak var userHostLabel: WKInterfaceLabel! + + let session = WCSession.default override func awake(withContext context: Any?) { super.awake(withContext: context) + + session.delegate = self + session.activate() // MARK: - Temperature @@ -301,3 +309,17 @@ class InterfaceController: WKInterfaceController { hideTimeOnce() } } + +extension InterfaceController: WCSessionDelegate { + func session(_ session: WCSession, activationDidCompleteWith activationState: WCSessionActivationState, error: Error?) { + + } + + func session(_ session: WCSession, didReceiveMessage message: [String : Any]) { + let username = message["username"] as? String ?? "user" + let hostname = message["hostname"] as? String ?? "watch" + + self.userHostLabelNow.setText(username + "@" + hostname + ":~ $ now") + self.userHostLabel.setText(username + "@" + hostname + ":~ $") + } +} diff --git a/TermiWatch/Base.lproj/LaunchScreen.storyboard b/TermiWatch/Base.lproj/LaunchScreen.storyboard index bfa3612..1abc00d 100644 --- a/TermiWatch/Base.lproj/LaunchScreen.storyboard +++ b/TermiWatch/Base.lproj/LaunchScreen.storyboard @@ -1,7 +1,9 @@ - - + + + - + + @@ -11,10 +13,10 @@ - + - + diff --git a/TermiWatch/Base.lproj/Main.storyboard b/TermiWatch/Base.lproj/Main.storyboard index a551298..f454de3 100644 --- a/TermiWatch/Base.lproj/Main.storyboard +++ b/TermiWatch/Base.lproj/Main.storyboard @@ -1,12 +1,11 @@ - - - - + + - + + @@ -15,14 +14,129 @@ - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/TermiWatch/ViewController.swift b/TermiWatch/ViewController.swift index 826418b..2be92bf 100644 --- a/TermiWatch/ViewController.swift +++ b/TermiWatch/ViewController.swift @@ -4,6 +4,7 @@ import PMKCoreLocation import PMKHealthKit import PromiseKit import UIKit +import WatchConnectivity let hkDataTypesOfInterest = Set([ HKObjectType.activitySummaryType(), @@ -15,8 +16,18 @@ let hkDataTypesOfInterest = Set([ ]) class ViewController: UIViewController { + @IBOutlet weak var usernameTextfield: UITextField! + @IBOutlet weak var hostnameTextfield: UITextField! + @IBOutlet weak var warningLabel: UILabel! + + var session: WCSession? + override func viewDidLoad() { super.viewDidLoad() + + self.warningLabel.isHidden = true + + createWCSession() firstly { CLLocationManager.requestAuthorization() @@ -26,4 +37,49 @@ class ViewController: UIViewController { print("Error:", $0) } } + + func createWCSession() { + if WCSession.isSupported() { + session = WCSession.default + session?.delegate = self + session?.activate() + } + } + + @IBAction func updateConfigToWatch(_ sender: UIButton) { + let username: String = self.usernameTextfield.text! + let hostname: String = self.hostnameTextfield.text! + if !isInputLengthValid(username: username, hostname: hostname) { return } + + let data = ["username": username, + "hostname": hostname] + + if let validSession = self.session, validSession.isReachable { + validSession.sendMessage(data, replyHandler: nil, errorHandler: nil) + } + } + + func isInputLengthValid(username: String, hostname: String) -> Bool { + self.warningLabel.isHidden = true + if (username.count > 4 || hostname.count > 5) { + self.warningLabel.isHidden = false + return false + } + + return true + } +} + +extension ViewController: WCSessionDelegate { + func session(_ session: WCSession, activationDidCompleteWith activationState: WCSessionActivationState, error: Error?) { + + } + + func sessionDidBecomeInactive(_ session: WCSession) { + + } + + func sessionDidDeactivate(_ session: WCSession) { + + } } From c4bf471c51e6eaadd1bf2dcb5b8535c7763a60d7 Mon Sep 17 00:00:00 2001 From: "HY. Kelvin Lee" Date: Thu, 22 Jul 2021 13:08:52 -0700 Subject: [PATCH 3/9] update max input characters condition --- TermiWatch/Base.lproj/Main.storyboard | 37 +++++++++++++++------------ TermiWatch/ViewController.swift | 2 +- 2 files changed, 22 insertions(+), 17 deletions(-) diff --git a/TermiWatch/Base.lproj/Main.storyboard b/TermiWatch/Base.lproj/Main.storyboard index f454de3..2a79c67 100644 --- a/TermiWatch/Base.lproj/Main.storyboard +++ b/TermiWatch/Base.lproj/Main.storyboard @@ -21,16 +21,16 @@ - + - + @@ -43,6 +43,7 @@ + @@ -54,16 +55,16 @@ - + - + @@ -73,6 +74,7 @@ + @@ -86,25 +88,28 @@ + - - + + + + - + + diff --git a/TermiWatch/ViewController.swift b/TermiWatch/ViewController.swift index 2be92bf..fbfa339 100644 --- a/TermiWatch/ViewController.swift +++ b/TermiWatch/ViewController.swift @@ -61,7 +61,7 @@ class ViewController: UIViewController { func isInputLengthValid(username: String, hostname: String) -> Bool { self.warningLabel.isHidden = true - if (username.count > 4 || hostname.count > 5) { + if (username.count + hostname.count > 9) { self.warningLabel.isHidden = false return false } From 885582812fdeb3444afe4dd4418147580208ab94 Mon Sep 17 00:00:00 2001 From: "HY. Kelvin Lee" Date: Thu, 22 Jul 2021 13:46:11 -0700 Subject: [PATCH 4/9] added keyboard dismissal function --- TermiWatch/Base.lproj/Main.storyboard | 6 +++--- TermiWatch/ViewController.swift | 8 ++++++++ 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/TermiWatch/Base.lproj/Main.storyboard b/TermiWatch/Base.lproj/Main.storyboard index 2a79c67..a8ace40 100644 --- a/TermiWatch/Base.lproj/Main.storyboard +++ b/TermiWatch/Base.lproj/Main.storyboard @@ -86,7 +86,7 @@ - + diff --git a/TermiWatch/ViewController.swift b/TermiWatch/ViewController.swift index fbfa339..dc1ca2e 100644 --- a/TermiWatch/ViewController.swift +++ b/TermiWatch/ViewController.swift @@ -28,6 +28,9 @@ class ViewController: UIViewController { self.warningLabel.isHidden = true createWCSession() + + let dismissalTap = UITapGestureRecognizer(target: self, action: #selector(dismissKeyboard)) + view.addGestureRecognizer(dismissalTap) firstly { CLLocationManager.requestAuthorization() @@ -68,6 +71,11 @@ class ViewController: UIViewController { return true } + + @objc func dismissKeyboard() { + // Causes the view (or one of its embedded text fields) to resign the first responder status. + view.endEditing(true) + } } extension ViewController: WCSessionDelegate { From ae688958d6c2644c50cceae6fd863bee2aeb0860 Mon Sep 17 00:00:00 2001 From: "HY. Kelvin Lee" Date: Fri, 6 Aug 2021 12:47:52 -0700 Subject: [PATCH 5/9] added calendar group component --- .../Base.lproj/Interface.storyboard | 38 +++- .../InterfaceController.swift | 19 ++ .../TermiWatch WatchKit App.xcscheme | 25 ++- TermiWatch/Base.lproj/Main.storyboard | 180 +++++++++++++++++- TermiWatch/ViewController.swift | 26 ++- 5 files changed, 274 insertions(+), 14 deletions(-) diff --git a/TermiWatch WatchKit App/Base.lproj/Interface.storyboard b/TermiWatch WatchKit App/Base.lproj/Interface.storyboard index 6315964..1ce74d9 100644 --- a/TermiWatch WatchKit App/Base.lproj/Interface.storyboard +++ b/TermiWatch WatchKit App/Base.lproj/Interface.storyboard @@ -105,7 +105,36 @@ + + + - + + @@ -125,11 +286,18 @@ - + + + + + + + + diff --git a/TermiWatch/ViewController.swift b/TermiWatch/ViewController.swift index dc1ca2e..cd12eb5 100644 --- a/TermiWatch/ViewController.swift +++ b/TermiWatch/ViewController.swift @@ -18,6 +18,12 @@ let hkDataTypesOfInterest = Set([ class ViewController: UIViewController { @IBOutlet weak var usernameTextfield: UITextField! @IBOutlet weak var hostnameTextfield: UITextField! + @IBOutlet weak var temperatureSwitch: UISwitch! + @IBOutlet weak var batterySwitch: UISwitch! + @IBOutlet weak var activitySwitch: UISwitch! + @IBOutlet weak var stepSwitch: UISwitch! + @IBOutlet weak var hrSwitch: UISwitch! + @IBOutlet weak var calendarSwitch: UISwitch! @IBOutlet weak var warningLabel: UILabel! var session: WCSession? @@ -29,6 +35,8 @@ class ViewController: UIViewController { createWCSession() + setDefaultSwitchesStatus() + let dismissalTap = UITapGestureRecognizer(target: self, action: #selector(dismissKeyboard)) view.addGestureRecognizer(dismissalTap) @@ -49,13 +57,28 @@ class ViewController: UIViewController { } } + func setDefaultSwitchesStatus() { + self.temperatureSwitch.setOn(true, animated: false) + self.batterySwitch.setOn(true, animated: false) + self.activitySwitch.setOn(true, animated: false) + self.stepSwitch.setOn(true, animated: false) + self.hrSwitch.setOn(true, animated: false) + self.calendarSwitch.setOn(false, animated: false) + } + @IBAction func updateConfigToWatch(_ sender: UIButton) { let username: String = self.usernameTextfield.text! let hostname: String = self.hostnameTextfield.text! if !isInputLengthValid(username: username, hostname: hostname) { return } let data = ["username": username, - "hostname": hostname] + "hostname": hostname, + "temperature": self.temperatureSwitch.isOn, + "battery": self.batterySwitch.isOn, + "activity": self.activitySwitch.isOn, + "steps": self.stepSwitch.isOn, + "heart-rate": self.hrSwitch.isOn, + "calendar": self.calendarSwitch.isOn] as [String : Any] if let validSession = self.session, validSession.isReachable { validSession.sendMessage(data, replyHandler: nil, errorHandler: nil) @@ -65,6 +88,7 @@ class ViewController: UIViewController { func isInputLengthValid(username: String, hostname: String) -> Bool { self.warningLabel.isHidden = true if (username.count + hostname.count > 9) { + self.warningLabel.text = "Max total Characters for username and hostname: 9" self.warningLabel.isHidden = false return false } From 3648c6ae36212b3b3f6b8e2af8246a618545abd9 Mon Sep 17 00:00:00 2001 From: "HY. Kelvin Lee" Date: Fri, 6 Aug 2021 14:57:03 -0700 Subject: [PATCH 6/9] added calendar feature on watch --- TermiWatch WatchKit Extension/Info.plist | 2 + .../InterfaceController.swift | 44 +++++++++++++++++++ TermiWatch/Info.plist | 2 + TermiWatch/ViewController.swift | 5 +++ 4 files changed, 53 insertions(+) diff --git a/TermiWatch WatchKit Extension/Info.plist b/TermiWatch WatchKit Extension/Info.plist index d89d604..d8912dd 100644 --- a/TermiWatch WatchKit Extension/Info.plist +++ b/TermiWatch WatchKit Extension/Info.plist @@ -34,6 +34,8 @@ Your health records will be used to display activity data. NSLocationWhenInUseUsageDescription Your location data will be used to display weather data. + NSCalendarsUsageDescription + Your calendar data will be used to display event OpenWeatherMapAPIKey 8d30dae09830ab2917caface6d6cf1c5 WKExtensionDelegateClassName diff --git a/TermiWatch WatchKit Extension/InterfaceController.swift b/TermiWatch WatchKit Extension/InterfaceController.swift index 7d62bbf..caacbdf 100644 --- a/TermiWatch WatchKit Extension/InterfaceController.swift +++ b/TermiWatch WatchKit Extension/InterfaceController.swift @@ -1,5 +1,6 @@ import Foundation import HealthKit +import EventKit import PMKCoreLocation import PMKHealthKit import PromiseKit @@ -219,7 +220,50 @@ class InterfaceController: WKInterfaceController { }.catch { print("Error:", $0) } + + // MARK: - Calendar + + let store = EKEventStore() + + let ekStatus = EKEventStore.authorizationStatus(for: .event) + switch (ekStatus) { + case EKAuthorizationStatus.notDetermined: + store.requestAccess(to: .event) { granted, error in + // Handle the response to the request. + } + self.calendarLabel.setText("notDetermined") + case EKAuthorizationStatus.authorized: + // Get the appropriate calendar. + let calendar = Calendar.current + + // Create the start date components + var oneDayAgoComponents = DateComponents() + oneDayAgoComponents.day = -1 + let oneDayAgo = calendar.date(byAdding: oneDayAgoComponents, to: Date()) + + // Create the end date components. + var oneYearFromNowComponents = DateComponents() + oneYearFromNowComponents.year = 1 + let oneYearFromNow = calendar.date(byAdding: oneYearFromNowComponents, to: Date()) + + // Create the predicate from the event store's instance method. + var predicate: NSPredicate? = nil + if let anAgo = oneDayAgo, let aNow = oneYearFromNow { + predicate = store.predicateForEvents(withStart: anAgo, end: aNow, calendars: nil) + } + // Fetch all events that match the predicate. + var events: [EKEvent]? = nil + if let aPredicate = predicate { + events = store.events(matching: aPredicate) + self.calendarLabel.setText(events?[0].title) + } + case EKAuthorizationStatus.restricted, EKAuthorizationStatus.denied: + self.calendarLabel.setText("restricted") + default: + self.calendarLabel.setText("error") + } + // MARK: - Health let healthStore = HKHealthStore() diff --git a/TermiWatch/Info.plist b/TermiWatch/Info.plist index 363c693..60aaa9d 100644 --- a/TermiWatch/Info.plist +++ b/TermiWatch/Info.plist @@ -26,6 +26,8 @@ Your health records will be used to display activity data. NSLocationWhenInUseUsageDescription Your location data will be used to display weather data. + NSCalendarsUsageDescription + Your calendar data will be used to display event UILaunchStoryboardName LaunchScreen UIMainStoryboardFile diff --git a/TermiWatch/ViewController.swift b/TermiWatch/ViewController.swift index cd12eb5..2af497f 100644 --- a/TermiWatch/ViewController.swift +++ b/TermiWatch/ViewController.swift @@ -1,5 +1,6 @@ import CoreLocation import HealthKit +import EventKit import PMKCoreLocation import PMKHealthKit import PromiseKit @@ -47,6 +48,10 @@ class ViewController: UIViewController { }.catch { print("Error:", $0) } + + EKEventStore().requestAccess(to: .event) { granted, error in + // Handle the response to the request. + } } func createWCSession() { From 14fddc3eb6a6ddad2489f965d6fd3afb6394b644 Mon Sep 17 00:00:00 2001 From: "HY. Kelvin Lee" Date: Fri, 6 Aug 2021 15:32:20 -0700 Subject: [PATCH 7/9] refactored event kit code --- .../EventKitUtils.swift | 36 +++++++++++++++++++ .../InterfaceController.swift | 33 +++-------------- TermiWatch.xcodeproj/project.pbxproj | 4 +++ .../TermiWatch WatchKit App.xcscheme | 25 ++++--------- 4 files changed, 50 insertions(+), 48 deletions(-) create mode 100644 TermiWatch WatchKit Extension/EventKitUtils.swift diff --git a/TermiWatch WatchKit Extension/EventKitUtils.swift b/TermiWatch WatchKit Extension/EventKitUtils.swift new file mode 100644 index 0000000..526dc4d --- /dev/null +++ b/TermiWatch WatchKit Extension/EventKitUtils.swift @@ -0,0 +1,36 @@ +import Foundation +import EventKit +import PromiseKit + +func eventRequestAccess(eventStore: EKEventStore) { + eventStore.requestAccess(to: .event) { granted, error in + // Handle the response to the request. + } +} + +func fetchTopEvent(eventStore: EKEventStore, calendar: Calendar) -> String { + // Create the start date components + var oneDayAgoComponents = DateComponents() + oneDayAgoComponents.day = -1 + let oneDayAgo = calendar.date(byAdding: oneDayAgoComponents, to: Date()) + + // Create the end date components. + var oneDayFromNowComponents = DateComponents() + oneDayFromNowComponents.day = 1 + let oneDayFromNow = calendar.date(byAdding: oneDayFromNowComponents, to: Date()) + + // Create the predicate from the event store's instance method. + var predicate: NSPredicate? = nil + if let anAgo = oneDayAgo, let aNow = oneDayFromNow { + predicate = eventStore.predicateForEvents(withStart: anAgo, end: aNow, calendars: nil) + } + + // Fetch all events that match the predicate. + var events: [EKEvent]? = nil + if let aPredicate = predicate { + events = eventStore.events(matching: aPredicate) + } + + let topEventTitle = events?[0].title ?? "No more events" + return topEventTitle +} diff --git a/TermiWatch WatchKit Extension/InterfaceController.swift b/TermiWatch WatchKit Extension/InterfaceController.swift index caacbdf..8b5cbc7 100644 --- a/TermiWatch WatchKit Extension/InterfaceController.swift +++ b/TermiWatch WatchKit Extension/InterfaceController.swift @@ -223,41 +223,16 @@ class InterfaceController: WKInterfaceController { // MARK: - Calendar - let store = EKEventStore() + let eventStore = EKEventStore() let ekStatus = EKEventStore.authorizationStatus(for: .event) - switch (ekStatus) { + switch ekStatus { case EKAuthorizationStatus.notDetermined: - store.requestAccess(to: .event) { granted, error in - // Handle the response to the request. - } + eventRequestAccess(eventStore: eventStore) self.calendarLabel.setText("notDetermined") case EKAuthorizationStatus.authorized: - // Get the appropriate calendar. let calendar = Calendar.current - - // Create the start date components - var oneDayAgoComponents = DateComponents() - oneDayAgoComponents.day = -1 - let oneDayAgo = calendar.date(byAdding: oneDayAgoComponents, to: Date()) - - // Create the end date components. - var oneYearFromNowComponents = DateComponents() - oneYearFromNowComponents.year = 1 - let oneYearFromNow = calendar.date(byAdding: oneYearFromNowComponents, to: Date()) - - // Create the predicate from the event store's instance method. - var predicate: NSPredicate? = nil - if let anAgo = oneDayAgo, let aNow = oneYearFromNow { - predicate = store.predicateForEvents(withStart: anAgo, end: aNow, calendars: nil) - } - - // Fetch all events that match the predicate. - var events: [EKEvent]? = nil - if let aPredicate = predicate { - events = store.events(matching: aPredicate) - self.calendarLabel.setText(events?[0].title) - } + self.calendarLabel.setText(fetchTopEvent(eventStore: eventStore, calendar: calendar)) case EKAuthorizationStatus.restricted, EKAuthorizationStatus.denied: self.calendarLabel.setText("restricted") default: diff --git a/TermiWatch.xcodeproj/project.pbxproj b/TermiWatch.xcodeproj/project.pbxproj index 5361797..55bb7b2 100644 --- a/TermiWatch.xcodeproj/project.pbxproj +++ b/TermiWatch.xcodeproj/project.pbxproj @@ -31,6 +31,7 @@ 5DD84FF8245F172E00E780A4 /* Swizzle in Frameworks */ = {isa = PBXBuildFile; productRef = 5DD84FF7245F172E00E780A4 /* Swizzle */; }; 5DD84FFB245F176400E780A4 /* PMKCoreLocation in Frameworks */ = {isa = PBXBuildFile; productRef = 5DD84FFA245F176400E780A4 /* PMKCoreLocation */; }; 5DD84FFD245F176800E780A4 /* PMKHealthKit in Frameworks */ = {isa = PBXBuildFile; productRef = 5DD84FFC245F176800E780A4 /* PMKHealthKit */; }; + B639AD6C26BDE85200895D4F /* EventKitUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = B639AD6B26BDE85200895D4F /* EventKitUtils.swift */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -100,6 +101,7 @@ 5DD84FE4245F12D800E780A4 /* TermiWatch WatchKit Extension.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = "TermiWatch WatchKit Extension.entitlements"; sourceTree = ""; }; 5DD84FE8245F132B00E780A4 /* TermiWatch.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = TermiWatch.entitlements; sourceTree = ""; }; 5DD84FE9245F134E00E780A4 /* SF-Mono-Regular.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "SF-Mono-Regular.otf"; sourceTree = ""; }; + B639AD6B26BDE85200895D4F /* EventKitUtils.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EventKitUtils.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -185,6 +187,7 @@ 5DD84FE1245F12D700E780A4 /* TemperatureNotifier.swift */, 5DD84FD1245F118500E780A4 /* Assets.xcassets */, 5DD84FD3245F118500E780A4 /* Info.plist */, + B639AD6B26BDE85200895D4F /* EventKitUtils.swift */, ); path = "TermiWatch WatchKit Extension"; sourceTree = ""; @@ -361,6 +364,7 @@ 5DD84FE7245F12D800E780A4 /* BatteryInfoNotifier.swift in Sources */, 5DD84FE6245F12D800E780A4 /* HealthKitUtils.swift in Sources */, 5DD84FCE245F118400E780A4 /* InterfaceController.swift in Sources */, + B639AD6C26BDE85200895D4F /* EventKitUtils.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/TermiWatch.xcodeproj/xcshareddata/xcschemes/TermiWatch WatchKit App.xcscheme b/TermiWatch.xcodeproj/xcshareddata/xcschemes/TermiWatch WatchKit App.xcscheme index d3f6ec3..717f1f7 100644 --- a/TermiWatch.xcodeproj/xcshareddata/xcschemes/TermiWatch WatchKit App.xcscheme +++ b/TermiWatch.xcodeproj/xcshareddata/xcschemes/TermiWatch WatchKit App.xcscheme @@ -54,10 +54,8 @@ debugDocumentVersioning = "YES" debugServiceExtension = "internal" allowLocationSimulation = "YES"> - + - + @@ -77,10 +75,8 @@ savedToolIdentifier = "" useCustomWorkingDirectory = "NO" debugDocumentVersioning = "YES"> - + - - - - - + From f4240d675d175f09fe7138196c9090b408147042 Mon Sep 17 00:00:00 2001 From: "HY. Kelvin Lee" Date: Tue, 10 Aug 2021 11:00:28 -0700 Subject: [PATCH 8/9] added event observer for event store --- TermiWatch WatchKit Extension/EventKitUtils.swift | 12 +++--------- .../InterfaceController.swift | 9 +++++++++ 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/TermiWatch WatchKit Extension/EventKitUtils.swift b/TermiWatch WatchKit Extension/EventKitUtils.swift index 526dc4d..3067f2f 100644 --- a/TermiWatch WatchKit Extension/EventKitUtils.swift +++ b/TermiWatch WatchKit Extension/EventKitUtils.swift @@ -10,20 +10,14 @@ func eventRequestAccess(eventStore: EKEventStore) { func fetchTopEvent(eventStore: EKEventStore, calendar: Calendar) -> String { // Create the start date components - var oneDayAgoComponents = DateComponents() - oneDayAgoComponents.day = -1 - let oneDayAgo = calendar.date(byAdding: oneDayAgoComponents, to: Date()) + let now = Date() // Create the end date components. - var oneDayFromNowComponents = DateComponents() - oneDayFromNowComponents.day = 1 - let oneDayFromNow = calendar.date(byAdding: oneDayFromNowComponents, to: Date()) + let tomorrow = Date().addingTimeInterval(60 * 60 * 24) // Create the predicate from the event store's instance method. var predicate: NSPredicate? = nil - if let anAgo = oneDayAgo, let aNow = oneDayFromNow { - predicate = eventStore.predicateForEvents(withStart: anAgo, end: aNow, calendars: nil) - } + predicate = eventStore.predicateForEvents(withStart: now, end: tomorrow, calendars: nil) // Fetch all events that match the predicate. var events: [EKEvent]? = nil diff --git a/TermiWatch WatchKit Extension/InterfaceController.swift b/TermiWatch WatchKit Extension/InterfaceController.swift index 8b5cbc7..5ccd704 100644 --- a/TermiWatch WatchKit Extension/InterfaceController.swift +++ b/TermiWatch WatchKit Extension/InterfaceController.swift @@ -239,6 +239,15 @@ class InterfaceController: WKInterfaceController { self.calendarLabel.setText("error") } + NotificationCenter.default.addObserver( + forName: .EKEventStoreChanged, + object: eventStore, + queue: nil + ) { [weak self] notification in + let calendar = Calendar.current + self?.calendarLabel.setText(fetchTopEvent(eventStore: eventStore, calendar: calendar)) + } + // MARK: - Health let healthStore = HKHealthStore() From cf0e4b90d05542726e74b4c956329bc87708d6d7 Mon Sep 17 00:00:00 2001 From: "HY. Kelvin Lee" Date: Tue, 7 Sep 2021 11:48:54 -0400 Subject: [PATCH 9/9] updated optional events array --- TermiWatch WatchKit Extension/EventKitUtils.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/TermiWatch WatchKit Extension/EventKitUtils.swift b/TermiWatch WatchKit Extension/EventKitUtils.swift index 3067f2f..8cf47cf 100644 --- a/TermiWatch WatchKit Extension/EventKitUtils.swift +++ b/TermiWatch WatchKit Extension/EventKitUtils.swift @@ -25,6 +25,6 @@ func fetchTopEvent(eventStore: EKEventStore, calendar: Calendar) -> String { events = eventStore.events(matching: aPredicate) } - let topEventTitle = events?[0].title ?? "No more events" + let topEventTitle = events?.first?.title ?? "No more events" return topEventTitle }