复杂功能适用于模拟器,但不适用于设备

Complication works on Simulator, but not on Device

我有一个并发症,在模拟器上工作,但在实际设备上不工作当我 TestFlight 它在实际设备上测试时(为了清楚起见,如果有有什么困惑吗,我不是在谈论通过设备进行调试,而是在测试它是否可以在设备上运行。

具体来说,在 Watch 设备上:

Info 在 iPhone:

    game.duel = playoffs[“Duel”] as! String
    game.tv = playoffs[“TV”] as! String
    game.td = playoffs[“TD”] as! AnyObject
    let dictionary = [“Duel” : game.duel, “TV” : game.tv, “TD” : game.td]
    let transferComplication = WCSession.defaultSession().transferCurrentComplicationUserInfo(dictionary)

ExtensionDelegate 在 WatchKit 扩展中:

    var duelArray = [String]()
    var tvArray = [String]()
    var tdArray = [NSDate]()
    let defaults = NSUserDefaults.standardUserDefaults()

        if let duel = userInfo[“Duel”] as? String, let tv = userInfo[“TV”] as? String, let td = userInfo[“TD”] as? String {
            duelArray.append(duel)
            tvArray.append(tv)
            tdArray.append(td as! NSDate)
            defaults.setObject(duelArray, forKey: “DuelSaved”)
            defaults.setObject(tvArray, forKey: "TVSaved”)
            defaults.setObject(tdArray, forKey: "TDSaved”)
}

ComplicationController 在 WatchKit 扩展中:

    func getCurrentTimelineEntryForComplication(complication: CLKComplication, withHandler handler: ((CLKComplicationTimelineEntry?) -> Void)) {
switch complication.family {
        case .ModularLarge:
            let mlTemplate = CLKComplicationTemplateModularLargeStandardBody()
                if let currentDuel = defaults.arrayForKey(“DuelSaved”) as? [String] {
                        let firstDuel = currentDuel[0]
                        let headerTextProvider = CLKSimpleTextProvider(text: firstDuel)
                        mlTemplate.headerTextProvider = headerTextProvider
                } else {
                    // …

                }
                if let currentTV = defaults.arrayForKey(“TVSaved”) as? [String] {
                    let firstTV = currentTV[0]
                    let body1TextProvider = CLKSimpleTextProvider(text: firstTV)
                    mlTemplate.body1TextProvider = body1TextProvider
                } else {
                    // …
                }
                if let currentTD = defaults.arrayForKey("TDSaved"){
                        let firstTD = currentTD[0]
                        let body2TextProvider = CLKTimeTextProvider(date: firstTD as! NSDate)
                        mlTemplate.body2TextProvider = body2TextProvider
                } else {
                    // …
                }
                let timelineEntry = CLKComplicationTimelineEntry(date: NSDate(), complicationTemplate: mlTemplate)
                handler(timelineEntry)
    // …
}


    func getTimelineEntriesForComplication(complication: CLKComplication, afterDate date: NSDate, limit: Int, withHandler handler: (([CLKComplicationTimelineEntry]?) -> Void)) {
        let headerArray = defaults.arrayForKey(“DuelSaved”)
        let body1Array = defaults.arrayForKey("TVSaved")
        let body2Array = defaults.arrayForKey("TDSaved")

        guard let headers = headerArray, texts = body1Array, dates = body2Array else { return }
        var entries = [CLKComplicationTimelineEntry]()
for (index, header) in headers.enumerate() {
            let text = texts[index]
            let date1 = dates[index]
            let headerTextProvider = CLKSimpleTextProvider(text: header as! String, shortText: headerShort as? String)
            let body1TextProvider = CLKSimpleTextProvider(text: text as! String)
            let timeTextProvider = CLKTimeTextProvider(date: date1 as! NSDate)
            let template = CLKComplicationTemplateModularLargeStandardBody()

            template.headerTextProvider = headerTextProvider
            template.body1TextProvider = body1TextProvider
            template.body2TextProvider = timeTextProvider

            switch complication.family {
            case .ModularLarge:
                let timelineEntry = CLKComplicationTimelineEntry(date: date1 as! NSDate, complicationTemplate: template)
                entries.append(timelineEntry)
            // …
}

    func requestedUpdateDidBegin() {        
        let server=CLKComplicationServer.sharedInstance()
        for comp in (server.activeComplications) {
            server.reloadTimelineForComplication(comp)
        }
    }

这是数据的流向:

transferCurrentComplicationUserInfo 将数据传递给手表 ExtensionDelegate,其中数据保存在 NSUserDefaults 中。 ComplicationController 然后从 NSUserDefaults.

中提取初始数据

乍一看:

  • 这似乎不是工作代码,因为您会看到很多关于 "Unicode curly quote found, ...".

    的 Xcode 修复错误
  • 请避免使用 as! 强制向下转换,因为它可能会失败并且您的代码会崩溃。您进行了很多不必要的类型转换。 ,您应该键入变量以允许编译器捕获任何程序员错误。

    例如,如果您的字典的键和值都是字符串,则安全地将其键入为:

    var playoffs: [String: String]
    
  • 如果无法进行 as? 向下转换(因为您传递的内容与您预期收到的内容不同),您的扩展委托代码可能有条件地失败。确保您传递的是您期望的值类型,否则整个块不会 运行。您可以通过设置断点并单步执行该代码轻松地在调试器中进行检查。

    您还需要在收到信息后明确更新您的并发症。

    func session(session: WCSession, didReceiveUserInfo userInfo: [String : AnyObject]) {
        if let ... { // Retrieve values from dictionary
    
            // Update complication
            let complicationServer = CLKComplicationServer.sharedInstance()
            guard let activeComplications = complicationServer.activeComplications else { // watchOS 2.2
                return
            }
    
            for complication in activeComplications {
                complicationServer.reloadTimelineForComplication(complication)
            }
        }
    }
    
  • 你用数组和 NSUserDefaults 做的事情真是令人费解。虽然在启动之间 持久化数据是完全合适的,但 NSUserDefaults 绝不是将代码的一部分 "pass" 详细信息转移到另一部分的方法。

    您的复杂数据源应该从模型或数据管理器中获取数据,而不是从 NSUserDefaults.

  • getCurrentTimelineEntryForComplicationif let ... { } else {代码没有意义。如果你没有得到一个字符串数组,你希望在 else 块中做什么?

    你也可以在 switch 语句之前准备你的数据,让你的代码更具可读性和紧凑性,像这样:

    func getCurrentTimelineEntryForComplication(complication: CLKComplication, withHandler handler: ((CLKComplicationTimelineEntry?) -> Void)) {
        // Call the handler with the current timeline entry
    
        let recentData = DataManager.sharedManager.complicationData ?? "???"
    
        let template: CLKComplicationTemplate?
        let simpleTextProvider = CLKSimpleTextProvider(text: recentData)
    
        switch complication.family {
        case .ModularLarge:
            let modularLargeTemplate = CLKComplicationTemplateModularLargeStandardBody()
            modularLargeTemplate.headerTextProvider = CLKSimpleTextProvider(text: "Update Complication", shortText: "Update")
            modularLargeTemplate.body1TextProvider = simpleTextProvider
            template = modularLargeTemplate
        case .UtilitarianLarge:
            let utilitarianLargeTemplate = CLKComplicationTemplateUtilitarianLargeFlat()
            utilitarianLargeTemplate.textProvider = simpleTextProvider
            template = utilitarianLargeTemplate
        case .CircularSmall:
            let circularSmallTemplate = CLKComplicationTemplateCircularSmallSimpleText()
            circularSmallTemplate.textProvider = simpleTextProvider
            template = circularSmallTemplate
        case .ModularSmall:
            let modularSmallTemplate = CLKComplicationTemplateModularSmallSimpleText()
            modularSmallTemplate.textProvider = simpleTextProvider
            template = modularSmallTemplate
        case .UtilitarianSmall:
            let utilitarianSmallTemplate = CLKComplicationTemplateUtilitarianSmallFlat()
            utilitarianSmallTemplate.textProvider = simpleTextProvider
            template = utilitarianSmallTemplate
        }
        let timelineEntry = CLKComplicationTimelineEntry(date: NSDate(), complicationTemplate: template!)
        handler(timelineEntry)
    }
    

可能的问题是 ClockKit 要求复杂数据,远在 您的扩展甚至收到它之前,因此您的复杂数据源没有数据可提供,并且没有条目出现。

即使某些事情碰巧在模拟器上运行,但这并不意味着您的代码也可以在实际设备上运行。有各种各样的差异可以解释为什么它不能在真实硬件上工作,这就是为什么你绝对需要在设备上进行交互调试。它将帮助您了解为什么您的代码没有按预期工作。

理想情况下,您应该在来这里之前进行这种类型的交互式调试并解决其他问题,这样您就可以用最少的工作代码块提出非常具体的问题.需要某人广泛调试您的代码的问题通常对其他人没有用。