简体   繁体   English

并发症只能在模拟器上使用,而不能在设备上使用

[英]Complication works on Simulator, but not on Device

I have a complication that works on Simulator, but doesn't work on an actual device when I TestFlight it to test on an actual device (and for clarity sake if there is any confusion, I'm not talking about debugging via device, but just testing if it works on a device). 我有一个适用于Simulator的复杂功能,但是当我对它进行TestFlight测试以在实际设备上进行测试时,却无法在实际设备上运行(为了清楚起见,如果有任何混淆,我不是在谈论通过设备进行调试,而是只是测试它是否可以在设备上运行)。

Specifically, on the Watch device: 具体来说,在Watch设备上:

  • I select the Complication on the Watch thru customizing the clock face, which gives me the placeholder text (so far so good because getPlaceholderTemplateForComplication works on Simulator too)... 我通过自定义钟面在手表上选择了Complication,这为我提供了占位符文本(到目前为止非常好,因为getPlaceholderTemplateForComplication可以在Simulator上运行)...
  • but then the Complication always stays as the placeholder text (not correct because getCurrentTimelineEntryForComnplication works on Simulator)... 但随后,“并发症”始终保持为占位符文本(不正确,因为getCurrentTimelineEntryForComnplication在Simulator上有效)...
  • even when scrolling thru Time Travel the placeholder text doesn't change but just dims (not correct because getTimelineEntriesForComplication:afterDate works on Simulator)... 即使在时间旅行中滚动时,占位符文本也不会改变,只是变暗(不正确,因为getTimelineEntriesForComplication:afterDate在Simulator上有效)...

Info on iPhone: iPhone上的Info

    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 in WatchKit Extension: 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 in WatchKit Extension: WatchKit扩展中的ComplicationController

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

This is the flow of the data: 这是数据流:

transferCurrentComplicationUserInfo passes data to the Watch ExtensionDelegate wherein the data is saved in NSUserDefaults . transferCurrentComplicationUserInfo将数据传递到Watch ExtensionDelegate其中数据保存在NSUserDefaults ComplicationController then pulls its initial data from NSUserDefaults . 然后, ComplicationControllerNSUserDefaults其初始数据。

At first glance: 乍一看:

  • This doesn't appear to be working code, as you'd be seeing a lot of Xcode fix-it errors about "Unicode curly quote found, ...". 这似乎不是有效的代码,因为您会看到很多有关“发现Unicode弯引号,...”的Xcode修复错误。

  • Please avoid force downcasting with as! 请避免用as!强制向下转换as! as it can fail and your code will crash. 因为它可能会失败,并且您的代码将崩溃。 You've got lots of unnecessary type casting taking place. 您发生了很多不必要的类型转换。 As I mentioned before , you should be typing your variables to allow the compiler to catch any programmer errors. 如前所述 ,您应该输入变量以允许编译器捕获任何程序员错误。

    For example, if your dictionary's keys and values are both strings, then safely type it as: 例如,如果字典的键和值都是字符串,则可以安全地将其键入为:

     var playoffs: [String: String] 
  • Your extension delegate code may conditionally fail, if the as? 您的扩展委托代码可能有条件地失败,如果as? downcast is not possible (because you passed something different than what you expected to receive). 无法进行向下转换(因为您传递的内容与预期的有所不同)。 Make sure you're passing the types of values that you expect, or that whole block won't run. 确保传递的是您期望的值类型,否则整个代码块将无法运行。 You can easily check that in the debugger by setting a breakpoint and stepping through that code. 您可以通过设置断点并逐步执行该代码来轻松地在调试器中检查该代码。

    You also need to explicitly update your complication, once the info is received. 收到信息后,您还需要显式更新并发症。

     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) } } } 
  • It's really convoluted what you're doing with the arrays and NSUserDefaults . 确实NSUserDefaults了您使用数组和NSUserDefaults所做的NSUserDefaults While it's perfectly appropriate to persist data between launches, NSUserDefaults is never meant to be a way to "pass" details from one part of your code to another. 尽管 NSUserDefaults 启动之间持久保存数据是非常合适的,但 NSUserDefaults绝不意味着将细节从代码的一部分传递到另一部分。

    Your complication data source should get its data from a model or data manager, instead of from NSUserDefaults . 您的复杂数据源应该从模型或数据管理器而不是从NSUserDefaults获取数据。

  • The getCurrentTimelineEntryForComplication if let ... { } else { code makes no sense. if let ... { } else {代码,则没有意义的getCurrentTimelineEntryForComplication If you didn't get an array of strings, what do you expect to do in the else block? 如果没有得到一个字符串数组,那么您期望在else块中做else

    You can also prepare your data before the switch statement, to make your code more readable and compact, like so: 您还可以在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) } 

The likely issue is that ClockKit asked for complication data, well before your extension even received it, so your complication data source had no data to provide, and no entries appear. 可能的问题是ClockKit 您的扩展程序甚至没有收到并发症数据之前就要求它提供数据,因此您的并发症数据源没有要提供的数据,也没有条目出现。

Even though something happens to work on the simulator, it doesn't mean your code is robust to also work on the actual device. 即使在模拟器上发生了某些事情,这并不意味着您的代码也可以在实际设备上运行。 There are all sorts of differences that can account for why it won't work on the real hardware, which is why you absolutely need to debug interactively on the device. 有各种各样的差异可以解释为什么它不能在实际的硬件上运行,这就是为什么您绝对需要在设备上进行交互式调试的原因。 It will help you realize why your code isn't working as intended. 它将帮助您了解为什么代码无法按预期工作。

Ideally, you should be doing this type of interactive debugging and solving those other issues before coming here, so you can ask a very specific question with a minimal working block of code. 理想情况下,您应该在进行此类型的交互式调试之前,先解决其他问题,然后才能用最少的工作代码块提出一个非常具体的问题。 Questions which require someone to broadly debug your code really aren't useful to others in general. 一般而言,那些需要某人广泛调试您的代码的问题实际上并没有帮助。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM