0

我有一个可以在模拟器上运行的复杂功能,但是当我在实际设备上进行 TestFlight 测试时它不能在实际设备上运行(为了清楚起见,如果有任何混淆,我不是在谈论通过设备进行调试,而是只是测试它是否适用于设备)。

具体来说,在 Watch 设备上:

  • 我通过自定义钟面选择了手表上的复杂功能,这给了我占位符文本(到目前为止很好,因为 getPlaceholderTemplateForComplication也适用于模拟器)......
  • 但随后并发症始终保留为占位符文本(不正确,因为getCurrentTimelineEntryForComnplication适用于模拟器)...
  • 即使通过 Time Travel 滚动,占位符文本也不会改变,只是变暗(不正确,因为getTimelineEntriesForComplication:afterDate适用于模拟器)......

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将数据传递给 Watch ExtensionDelegate,其中数据保存在NSUserDefaults. ComplicationController然后从 中提取其初始数据NSUserDefaults

4

1 回答 1

2

乍一看:

  • 这似乎不是工作代码,因为您会看到很多关于“发现 Unicode 卷引号,...”的 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持久保存数据是完全合适的,但绝不意味着将细节从代码的一部分“传递”到另一部分。

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

  • getCurrentTimelineEntryForComplication if 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就要求提供并发症数据,因此您的并发症数据源没有数据可提供,也没有条目出现。

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

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

于 2016-03-30T00:49:19.513 回答