0

シミュレーターで機能する複雑な機能がありますが、実際のデバイスでテストするために TestFlight を実行すると、実際のデバイスでは機能しません (混乱がある場合は明確にするために、デバイスを介したデバッグについて話しているのではありませんが、デバイスで動作するかどうかをテストするだけです)。

具体的には、Watch デバイスで:

  • 時計の文字盤をカスタマイズして、ウォッチのコンプリケーションを選択すると、プレースホルダー テキストが表示されます ( getPlaceholderTemplateForComplicationシミュレーターでも動作するので、これまでのところ非常に優れています)...
  • ただし、合併症は常にプレースホルダーテキストのままです(getCurrentTimelineEntryForComnplicationシミュレーターで動作するため正しくありません)...
  • タイムトラベルをスクロールしても、プレースホルダーのテキストは変更されず、薄暗くなります (getTimelineEntriesForComplication:afterDateシミュレーターで動作するため正しくありません)...

InfoiPhone の場合:

    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)

ExtensionDelegateWatchKit 拡張機能:

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

ComplicationControllerWatchKit 拡張機能:

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

これはデータの流れです:

transferCurrentComplicationUserInfoExtensionDelegateデータが に保存されている Watch にデータを渡しますNSUserDefaultsComplicationController次に、 から初期データを取得しNSUserDefaultsます。

4

1 に答える 1

2

一目見ただけで:

  • 「Unicode curly quote found, ...」に関する多くの Xcode fix-it エラーが表示されるため、これは機能するコードではないようです。

  • 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 に答える