【问题标题】:Apple Watch complications are not reliably updatedApple Watch 复杂功能无法可靠更新
【发布时间】:2019-02-18 15:06:17
【问题描述】:

我有一个 iPhone 应用程序,它可以将数据从 iPhone 应用程序直接发送到表盘以显示为复杂功能。

我使用WatchConnectivity框架创建了一个WCSession将数据从手机发送到手表。

我的数据存储在字典中,并使用WCSessiontransferCurrentComplicationUserInfo 方法发送到手表。 (这种方法一天可以使用大约 50 次,我知道这不是问题。)

transferCurrentComplicationUserInfo 方法似乎在我第一次尝试发送数据时起作用。

我的问题是我的 iPhone 应用程序要在一个会话中多次调用此函数,并且它只能在第一次可靠地工作。

当我发送第二组数据时,第一组数据仍保留在复杂功能中。通常,当我发送第三组时,会出现第二组。有时第二组永久显示,有时只显示一秒钟,然后显示第三组。

这是不一致的,这就是我遇到的问题。

是不是我设置有问题?

代码:

//iPhone code to send data to Apple Watch:

func sendComplication(complication: Complication) {
        guard let session = session else {
            delegate?.failedToSendComplication(reason: "Could not connect to your Apple Watch.")
            return
        }
        guard let context = convertComplicationToDictionary(complication: complication) else {
            delegate?.failedToSendComplication(reason: "Couldn't cast complication to a dictionary.")
            return
        }
        if session.remainingComplicationUserInfoTransfers > 0 {
            session.transferCurrentComplicationUserInfo(context)
            delegate?.didSendComplication()
        } else {
            delegate?.failedToSendComplication(reason: "Due to hardware limitations, you can only send a certain amount of complications in a day. You have exceeded that limit for today. You can still set complications from the Apple Watch app.")
        }
    }

// WatchKit Extension Delegate to receive and handle data sent from iPhone app

import WatchKit
import WatchConnectivity

class ExtensionDelegate: NSObject, WKExtensionDelegate {

    var session: WCSession?

    override init() {
        super.init()
        self.session = newWatchConnectivitySession()
    }

    func newWatchConnectivitySession() -> WCSession? {
        if WCSession.isSupported() {
            let session = WCSession.default
            session.delegate = self
            session.activate()
            return session
        }
        return nil
    }

    func reloadComplicationTimeline() {
        let server = CLKComplicationServer.sharedInstance()
        guard let activeComplicationFamilies = server.activeComplications else { return }
        for comp in activeComplicationFamilies {
            server.reloadTimeline(for: comp)
        }
    }

}

extension ExtensionDelegate: WCSessionDelegate {

    func sessionReachabilityDidChange(_ session: WCSession) {
        if session.activationState != .activated {
            self.session = newWatchConnectivitySession()
        }
    }

    // Receive info from iPhone app
    func session(_ session: WCSession, didReceiveUserInfo userInfo: [String : Any] = [:]) {
        // Parse dictionary and update data source
        reloadComplicationTimeline()
    }

    func session(_ session: WCSession, activationDidCompleteWith activationState: WCSessionActivationState, error: Error?) {
        guard let error = error else { return }
        print(error.localizedDescription)
    }
}

// 更新 //

经过进一步检查,我现在发现步骤发生了故障。

这是事件的顺序:

  1. 从 iPhone 应用调用sendComplication
  2. ExtensionDelegate 在 Watch 应用上初始化,设置 WCSession
  3. 并发症已更新(太早了 - 这是在WCSession 收到新数据之前)
  4. 调用WCSession didReceiveUserInfo委托方法,解析数据,更新数据源(来不及)
  5. 并发症被告知重新加载,但没有任何反应(可能是预算问题?)

【问题讨论】:

  • 我不确定您的更新意味着什么:这是您问题的解决方案吗?还是按正确顺序执行步骤后问题相同?
  • 这不是解决方案。我的意思是表明我发现我的应用程序以错误的顺序运行功能,我不知道为什么。
  • 你解决了吗?

标签: watchkit apple-watch watchconnectivity apple-watch-complication clockkit


【解决方案1】:

尝试以下方法:

func reloadComplicationTimeline() {
    #if os(watchOS)
    let server = CLKComplicationServer.sharedInstance()
    if let activeComplicationFamilies = server.activeComplications {
    for comp in activeComplicationFamilies {
        server.reloadTimeline(for: comp)
    }
   #endif
}



func sendComplication(complication: Complication) {
        guard WCSession.default.activationState == .activated else {
            delegate?.failedToSendComplication(reason: "Could not connect to your Apple Watch.")
            return
        }
        guard let context = convertComplicationToDictionary(complication: complication) else {
            delegate?.failedToSendComplication(reason: "Couldn't cast complication to a dictionary.")
            return
        }
        #if os(iOS)
        if WCSession.default.isComplicationEnabled {
            let userInfoTranser = WCSession.default.transferCurrentComplicationUserInfo(context)
            delegate?.didSendComplication()
        } else {
            delegate?.failedToSendComplication(reason: "Due to hardware limitations, you can only send a certain amount of complications in a day. You have exceeded that limit for today. You can still set complications from the Apple Watch app.")
        }
        #endif
    }

以下是 Apple 提供的一个很好的示例,可以为您提供更多帮助:source

【讨论】:

    【解决方案2】:

    正如您在更新中所描述的那样,您的 iPhone 应用会在手表设置其 WCSession 之前调用 session.transferCurrentComplicationUserInfo(context)。但是文档说:

    [transferCurrentComplicationUserInfo(_:)] 只能在 会话处于活动状态 - 也就是说,activationState 属性设置为 WCSessionActivationState.activated。调用此方法 非活动或停用会话是程序员错误。

    因此我建议您实现(如果您还没有这样做的话)WCSessionDelegate 函数session(_:activationDidCompleteWith:error:)(请参阅here),并仅在会话激活后传输并发症数据。

    【讨论】:

      【解决方案3】:

      重置 iPhone、Apple Watch 和 Mac 解决了这个问题。

      【讨论】:

        猜你喜欢
        • 2017-11-22
        • 2016-04-05
        • 1970-01-01
        • 1970-01-01
        • 2016-01-03
        • 2016-03-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多