I want to have something similar to what the timer app on iOS is doing - it somehow synchronises with apple watch and runs the timer on both devices. Couldn't figure out how they do that - any ideas?
-
you probably need [Handoff](https://developer.apple.com/handoff/) and read about [WCSession](https://developer.apple.com/documentation/watchconnectivity/wcsession) – Gonras Karols Dec 19 '22 at 18:45
1 Answers
Synchronizing an application, like the timer, between the Apple Watch and iPhone requires the use of multiple communications technologies. For example:
Your main focus will be on the WatchConnectivity framework as it is most important in this scenario
Bluetooth: This technology allows devices to connect and communicate with each other wirelessly. By using Bluetooth, the iPhone and the Apple Watch can establish a connection and transfer data between each other.
iCloud: This is Apple's cloud storage and synchronization service, which allows users to store and access their data on multiple devices. By using iCloud, the app can store data in the cloud and access it on both the iPhone and the Apple Watch, even if the devices are not connected via Bluetooth.
WatchConnectivity framework: This framework provides the necessary tools and APIs for the iPhone and the Apple Watch to communicate and transfer data between each other. By using the WatchConnectivity framework, the app can establish a connection between the two devices and transfer data as needed.
You gave the Timer app as an example. The Timer app requires the use of the WatchConnectivity framework as stated above. Here it is in action for both devices (this will require a user interface to be created, but this is the essence of the app):
iPhone
import UIKit
import WatchConnectivity
class ViewController: UIViewController, WCSessionDelegate {
// MARK: Properties
var timer: Timer?
var session: WCSession?
var startTime: Date?
// MARK: Lifecycle
override func viewDidLoad() {
super.viewDidLoad()
// Configure Watch Connectivity
if WCSession.isSupported() {
session = WCSession.default
session?.delegate = self
session?.activate()
}
}
// MARK: Action
@IBAction func startTapped(_ sender: Any) {
startTime = Date()
timer = Timer.scheduledTimer(timeInterval: 0.1, target: self, selector: #selector(updateTimer), userInfo: nil, repeats: true)
// Send start time to Watch
sendStartTimeToWatch()
}
@IBAction func stopTapped(_ sender: Any) {
// Stop timer
timer?.invalidate()
timer = nil
}
// MARK: Helper
@objc func updateTimer() {
// Calculate time elapsed
guard let startTime = startTime else { return }
let timeElapsed = Date().timeIntervalSince(startTime)
// Format time
let minutes = Int(timeElapsed) / 60 % 60
let seconds = Int(timeElapsed) % 60
// Update label
let timerString = String(format:"%02i:%02i", minutes, seconds)
// Update label
// Your label here
}
func sendStartTimeToWatch() {
guard let startTime = startTime, let session = session else { return }
do {
let data = try NSKeyedArchiver.archivedData(withRootObject: startTime, requiringSecureCoding: true)
try session.updateApplicationContext(["startTime": data])
} catch {
print("Error: \(error)")
}
}
// MARK: WCSessionDelegate
func session(_ session: WCSession, activationDidCompleteWith activationState: WCSessionActivationState, error: Error?) {
// no-op
}
}
Apple Watch
import WatchKit
import Foundation
import WatchConnectivity
class InterfaceController: WKInterfaceController, WCSessionDelegate {
// MARK: Properties
var timer: Timer?
var session: WCSession?
var startTime: Date?
// MARK: Lifecycle
override func awake(withContext context: Any?) {
super.awake(withContext: context)
// Configure Watch Connectivity
if WCSession.isSupported() {
session = WCSession.default
session?.delegate = self
session?.activate()
}
}
// MARK: Action
@IBAction func startTapped() {
// Receive start time from iPhone
receiveStartTimeFromiPhone()
}
@IBAction func stopTapped() {
// Stop timer
timer?.invalidate()
timer = nil
}
// MARK: Helper
func startTimer() {
guard let startTime = startTime else { return }
// Calculate time elapsed
let timeElapsed = Date().timeIntervalSince(startTime)
// Format time
let minutes = Int(timeElapsed) / 60 % 60
let seconds = Int(timeElapsed) % 60
// Update label
let timerString = String(format:"%02i:%02i", minutes, seconds)
// Update label
// Your label here
timer = Timer.scheduledTimer(timeInterval: 0.1, target: self, selector: #selector(updateTimer), userInfo: nil, repeats: true)
}
@objc func updateTimer() {
guard let startTime = startTime else { return }
// Calculate time elapsed
let timeElapsed = Date().timeIntervalSince(startTime)
// Format time
let minutes = Int(timeElapsed) / 60 % 60
let seconds = Int(timeElapsed) % 60
// Update label
let timerString = String(format:"%02i:%02i", minutes, seconds)
// Update label
// Your label here
}
func receiveStartTimeFromiPhone() {
guard let session = session else { return }
session.sendMessage(["request": "startTime"], replyHandler: { (response) in
if let data = response["startTime"] as? Data, let startTime = try? NSKeyedUnarchiver.unarchivedObject(ofClass: Date.self, from: data) {
self.startTime = startTime
self.startTimer()
}
}, errorHandler: { (error) in
print("Error: \(error)")
})
}
// MARK: WCSessionDelegate
func session(_ session: WCSession, activationDidCompleteWith activationState: WCSessionActivationState, error: Error?) {
// no-op
}
}

- 209
- 7
-
Thanks! Does that imply that the watch application is already open, or the awake method will be executed regardless of the user manually starting the app? – kovpas Dec 14 '22 at 07:48
-
It will activate upon waking the Apple Watch. But it still needs the interface; this is just the backend. There’s plenty of opportunity to expand upon it. – Masquerading Dec 14 '22 at 15:03
-
So user would have to wake up the watch… that was the question - if you check the timer app - it activates on the watch without any user interaction, when the timer finishes watch starts vibrating – kovpas Dec 14 '22 at 22:07
-
I see what you're saying. If the iPhone initiates a timer, the timer will begin running on the Watch without any wake. And once the timer finishes on the iPhone, it simultaneously vibrates on the Apple Watch. Based on your original post, I didn't know that was the functionality you had a question about. – Masquerading Dec 15 '22 at 01:10