4

我想通過WatchConnectivity從IOS/iPhone傳輸的數據更新watchOS2時鐘包的複雜性。更新WatchOS2與IOS數據的ClockKit併發症

儘管相當多的研究,迄今不成功。我發現,雖然其他職位描述類似的挑戰(沒有解決方案還)

現在面臨3個問題:

1)從ComplicationController的sendMessage似乎並沒有喚醒IOS父應用程序(而同樣的sendMessage從發InterfaceController不會喚醒IOS Parent App)

2)即使當值傳輸到ComplicationController(通過sendUserInfoToComplication和IOS應用程序在前臺)時,複雜程序中顯示的值僅有時會更新(未找到模式的原因有時它有/沒有)

3)我將「getNextRequestUpdate ..」設置爲2分鐘(用於測試目的)。這似乎沒有任何區別。 (甚至在任意時間模擬器觸發,但「預算」不利用/我設置塞子來驗證)

請注意,我是相對較新的IOS/Swift編程。但我看到,根據其他問題/帖子,我似乎並不是唯一一個正在爲此而努力的人。

下面的代碼示例:

ComplicationController

// 
// ComplicationController.swift 
// IOSDataToComplication WatchKit Extension 
// 
// Created by Thomas Peter on 11.10.2015. 
// Copyright © 2015 Thomas Peter. All rights reserved. 
// 

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() 

    } 

    // MARK: - Timeline Configuration 

    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) 
    } 

    // MARK: - Timeline Population 

    func getCurrentTimelineEntryForComplication(complication: CLKComplication, withHandler handler: ((CLKComplicationTimelineEntry?) -> Void)) { 
     // Call the handler with the current timeline entry 

     if complication.family == .ModularLarge { 

      //createData() 

      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)) { 
     // Call the handler with the timeline entries prior to the given date 
     handler(nil) 
    } 

    func getTimelineEntriesForComplication(complication: CLKComplication, afterDate date: NSDate, limit: Int, withHandler handler: (([CLKComplicationTimelineEntry]?) -> Void)) { 
     // Call the handler with the timeline entries after to the given date 
     handler(nil) 
    } 

    // MARK: - Update Scheduling 

    func getNextRequestedUpdateDateWithHandler(handler: (NSDate?) -> Void) { 
     // Call the handler with the date when you would next like to be given the opportunity to update your complication content 
     handler(NSDate(timeIntervalSinceNow: (60 * 2))) 
    } 

    // MARK: - Placeholder Templates 

    func getPlaceholderTemplateForComplication(complication: CLKComplication, withHandler handler: (CLKComplicationTemplate?) -> Void) { 
     // This method will be called once per supported complication, and the results will be cached 
     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 
      // handle reply from iPhone app here 

      //let answer:[String:AnyObject] = replyMessage 
      self.text = replyMessage["text"] as! String 
      print("complication received messagereply \(self.text)") 

      }, errorHandler: {(error) -> Void in 
       // catch any errors here 
       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()) { 

     //if text != textOld { 
      self.requestedUpdateDidBegin() 
     //} 
     } 
    } 




    private func startSession(){ 

     if (WCSession.isSupported()) { 
      session = WCSession.defaultSession() 
      session.delegate = self; 
      session.activateSession() 
     } 
    } 

} 

的ViewController

// 
// ViewController.swift 
// IOSDataToComplication 
// 
// Created by Thomas Peter on 11.10.2015. 
// Copyright © 2015 Thomas Peter. All rights reserved. 
// 

import UIKit 
import WatchConnectivity 


class ViewController: UIViewController, WCSessionDelegate { 

    var session:WCSession! 

    var time:String = "default" 

    var text:String = "default" 




    override func viewDidLoad() { 
     super.viewDidLoad() 
     // Do any additional setup after loading the view, typically from a nib. 

     startSession() 
     getData() 
     sendUserInfoToComplication() 
    } 

    override func didReceiveMemoryWarning() { 
     super.didReceiveMemoryWarning() 
     // Dispose of any resources that can be recreated. 
    } 


    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") 

    } 


} 

而且在運行模擬器的時候,我得到一個整數類似的消息如下:

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. 
+0

這裏的鏈接代碼:https://github.com/thpeter71/IOSDataToComplication.git – TPeter

+0

你有沒有得到這個整理出來? – bkwebhero

+0

不幸的不是。仍然與上面列出的所有3點戰鬥 – TPeter

回答

0

使用CLKComplicationServer這樣的:

CLKComplicationServer* server = [CLKComplicationServer sharedInstance]; 
[server.activeComplications enumerateObjectsUsingBlock:^(CLKComplication * _Nonnull each, NSUInteger idx, BOOL * _Nonnull stop) { 
    [server reloadTimelineForComplication: each]; 
}]; 

它會調用您ComplicationController

+0

謝謝你Jeeeyul。如果可能的話,我可以問你在Swift中的樣子嗎(我不知道客觀的C)?當我複製你的代碼(替換「let server = CLKComplicationServer.sharedInstance() for comp in(server.activeComplications){ server.reloadTimelineForComplication(comp) }'我得到一個錯誤列表(嘗試插入等等) ) – TPeter

0

在模擬器中調試複雜性時,您需要在每次從Xcode啓動調試會話之間退出手錶模擬器。如果你不這樣做,你會遇到7007錯誤所遇到的問題,getNextRequestedUpdateDateWithHandler將不會被調用。

這將更新您的併發症:

let server = CLKComplicationServer.sharedInstance() 
server.activeComplications.forEach { server.reloadTimelineForComplication($0) }