I am trying to update the clock synchronization of watchOS2 with data transferred via WatchConnectivity from IOS / iPhone.
Despite quite a lot of research, it has so far been unsuccessful. I found that other posts describe a similar problem (no solution)
In the face of three problems:
1) sendMessage from ComplicationController does not seem to wake up the IOS parent application (while the same sendMessage sent from InterfaceController wakes up the IOS parent application)
2), even when the value is passed to the ComplicationController (via sendUserInfoToComplication and when the IOS application is in the foreground), the value displayed during complication is sometimes updated sometimes (I did not find the template, why does it sometimes / sometimes not)
3) I set "getNextRequestUpdate .." for 2 minutes (for testing purposes). However, this does not matter. (It works even in the simulator at arbitrary points in time, but the "budget" is not used / I install probes for verification)
Please note that I am relatively new to IOS / Swift programming. But I see from other questions / posts that I seem to be not the only one struggling with this.
Here is an example code:
Complicationcontroller
import ClockKit
import WatchConnectivity
class ComplicationController: NSObject, CLKComplicationDataSource, WCSessionDelegate {
var session:WCSession!
var text:String = "watchdefault"
var textOld:String = ""
var header:String = "TestHeader"
override init(){
super.init()
startSession()
}
func getSupportedTimeTravelDirectionsForComplication(complication: CLKComplication, withHandler handler: (CLKComplicationTimeTravelDirections) -> Void) {
handler([.None])
}
func getTimelineStartDateForComplication(complication: CLKComplication, withHandler handler: (NSDate?) -> Void) {
handler(nil)
}
func getTimelineEndDateForComplication(complication: CLKComplication, withHandler handler: (NSDate?) -> Void) {
handler(nil)
}
func getPrivacyBehaviorForComplication(complication: CLKComplication, withHandler handler: (CLKComplicationPrivacyBehavior) -> Void) {
handler(.ShowOnLockScreen)
}
func getCurrentTimelineEntryForComplication(complication: CLKComplication, withHandler handler: ((CLKComplicationTimelineEntry?) -> Void)) {
if complication.family == .ModularLarge {
let entry = self.createTimeLineEntry(text, date: NSDate())
handler(entry)
} else {
handler(nil)
}
}
func getTimelineEntriesForComplication(complication: CLKComplication, beforeDate date: NSDate, limit: Int, withHandler handler: (([CLKComplicationTimelineEntry]?) -> Void)) {
handler(nil)
}
func getTimelineEntriesForComplication(complication: CLKComplication, afterDate date: NSDate, limit: Int, withHandler handler: (([CLKComplicationTimelineEntry]?) -> Void)) {
handler(nil)
}
func getNextRequestedUpdateDateWithHandler(handler: (NSDate?) -> Void) {
handler(NSDate(timeIntervalSinceNow: (60 * 2)))
}
func getPlaceholderTemplateForComplication(complication: CLKComplication, withHandler handler: (CLKComplicationTemplate?) -> Void) {
let template = CLKComplicationTemplateModularLargeStandardBody()
template.headerTextProvider = CLKSimpleTextProvider(text: "header")
template.body1TextProvider = CLKSimpleTextProvider(text:"defaul text")
handler(nil)
}
func requestedUpdateDidBegin() {
print("Complication update is starting")
createData()
let server=CLKComplicationServer.sharedInstance()
for comp in (server.activeComplications) {
server.reloadTimelineForComplication(comp)
print("Timeline has been reloaded!")
}
}
func requestedUpdateBudgetExhausted() {
print("Budget exhausted")
}
func createTimeLineEntry(bodyText: String, date:NSDate) -> CLKComplicationTimelineEntry {
let template = CLKComplicationTemplateModularLargeStandardBody()
template.headerTextProvider = CLKSimpleTextProvider(text: header)
template.body1TextProvider = CLKSimpleTextProvider(text: text)
let entry = CLKComplicationTimelineEntry(date: date, complicationTemplate: template)
return(entry)
}
func createData(){
let applicationData = ["wake":"fromComplication"]
session.sendMessage(applicationData, replyHandler: {(replyMessage: [String : AnyObject]) -> Void in
self.text = replyMessage["text"] as! String
print("complication received messagereply \(self.text)")
}, errorHandler: {(error ) -> Void in
print("no reply message")
})
print("complication sent \(applicationData) to iOS")
}
func session(session: WCSession, didReceiveUserInfo userInfo: [String : AnyObject]) {
textOld = text
text = userInfo["text"] as! String
print("complication received userinfo \(text)")
dispatch_async(dispatch_get_main_queue()) {
self.requestedUpdateDidBegin()
}
}
private func startSession(){
if (WCSession.isSupported()) {
session = WCSession.defaultSession()
session.delegate = self;
session.activateSession()
}
}
}
ViewController
import UIKit
import WatchConnectivity
class ViewController: UIViewController, WCSessionDelegate {
var session:WCSession!
var time:String = "default"
var text:String = "default"
override func viewDidLoad() {
super.viewDidLoad()
startSession()
getData()
sendUserInfoToComplication()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
func getData(){
let timeValue = NSDate()
let dateFormatter = NSDateFormatter()
dateFormatter.dateFormat = "hh:mm"
time = dateFormatter.stringFromDate(timeValue)
text = "iPhone \(time)"
print("constructed \(text)")
}
private func startSession(){
if (WCSession.isSupported()) {
session = WCSession.defaultSession()
session.delegate = self;
session.activateSession()
}
print("iPhone session started")
}
func session(session: WCSession, didReceiveMessage message: [String : AnyObject], replyHandler: ([String : AnyObject]) -> Void) {
let receivedMessage = message["wake"] as! String
print("iphone received message \(receivedMessage)")
let applicationDict = ["text":text]
replyHandler(applicationDict as [String : AnyObject])
getData()
}
func sendUserInfoToComplication(){
let applicationDict = ["text":text]
session.transferCurrentComplicationUserInfo(applicationDict)
print("iphone sent userinfo \(applicationDict) to complication")
}
}
In addition, when I start Simulator, I get a number of similar messages:
objc[7501]: Class SPAssetCacheAssets is implemented in both /Applications/Xcode.app/Contents/Developer/Platforms/WatchSimulator.platform/Developer/SDKs/WatchSimulator.sdk/System/Library/Frameworks/WatchKit.framework/WatchKit and /Applications/Xcode.app/Contents/Developer/Platforms/WatchSimulator.platform/Developer/SDKs/WatchSimulator.sdk/System/Library/PrivateFrameworks/SockPuppetGizmo.framework/SockPuppetGizmo. One of the two will be used. Which one is undefined.
objc[7501]: Class SPAssetCacheSyncData is implemented in both /Applications/Xcode.app/Contents/Developer/Platforms/WatchSimulator.platform/Developer/SDKs/WatchSimulator.sdk/System/Library/Frameworks/WatchKit.framework/WatchKit and /Applications/Xcode.app/Contents/Developer/Platforms/WatchSimulator.platform/Developer/SDKs/WatchSimulator.sdk/System/Library/PrivateFrameworks/SockPuppetGizmo.framework/SockPuppetGizmo. One of the two will be used. Which one is undefined.