Apple Watch 并发症无法可靠更新
Apple Watch complications are not reliably updated
我有一个 iPhone 应用程序,可以将数据从 iPhone 应用程序直接发送到表盘以显示为复杂功能。
我使用 WatchConnectivity
框架创建一个 WCSession
来将数据从 phone.
发送到手表
我的数据存储在字典中,并使用WCSession
的transferCurrentComplicationUserInfo
方法发送到手表。 (这种方法一天可以使用大约 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)
}
}
// 更新 //
经过进一步检查,我发现步骤出现了问题。
这是事件的顺序:
sendComplication
从 iPhone 应用程序调用
ExtensionDelegate
在 Watch 应用程序上初始化,设置 WCSession
- 并发症已更新(为时过早 - 这是在
WCSession
收到新数据之前)
- 调用
WCSession didReceiveUserInfo
委托方法,解析数据,更新数据源(来不及了)
- 并发症被告知重新加载,但没有任何反应(可能是预算问题?)
如您在更新中所述,您的 iPhone 应用会在手表设置其 WCSession
之前调用 session.transferCurrentComplicationUserInfo(context)
。但是文档说:
[transferCurrentComplicationUserInfo(_:)] can only be called while the
session is active - that is, the activationState property is set to
WCSessionActivationState.activated. Calling this method for an
inactive or deactivated session is a programmer error.
因此,我建议您实现(如果您还没有这样做的话)WCSessionDelegate
函数 session(_:activationDidCompleteWith:error:)
(参见 here),并且仅在会话之后传输并发症数据已激活。
尝试以下操作:
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
重置 iPhone、Apple Watch 和 Mac 解决了问题。
我有一个 iPhone 应用程序,可以将数据从 iPhone 应用程序直接发送到表盘以显示为复杂功能。
我使用 WatchConnectivity
框架创建一个 WCSession
来将数据从 phone.
我的数据存储在字典中,并使用WCSession
的transferCurrentComplicationUserInfo
方法发送到手表。 (这种方法一天可以使用大约 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)
}
}
// 更新 //
经过进一步检查,我发现步骤出现了问题。
这是事件的顺序:
sendComplication
从 iPhone 应用程序调用ExtensionDelegate
在 Watch 应用程序上初始化,设置WCSession
- 并发症已更新(为时过早 - 这是在
WCSession
收到新数据之前) - 调用
WCSession didReceiveUserInfo
委托方法,解析数据,更新数据源(来不及了) - 并发症被告知重新加载,但没有任何反应(可能是预算问题?)
如您在更新中所述,您的 iPhone 应用会在手表设置其 WCSession
之前调用 session.transferCurrentComplicationUserInfo(context)
。但是文档说:
[transferCurrentComplicationUserInfo(_:)] can only be called while the session is active - that is, the activationState property is set to WCSessionActivationState.activated. Calling this method for an inactive or deactivated session is a programmer error.
因此,我建议您实现(如果您还没有这样做的话)WCSessionDelegate
函数 session(_:activationDidCompleteWith:error:)
(参见 here),并且仅在会话之后传输并发症数据已激活。
尝试以下操作:
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
重置 iPhone、Apple Watch 和 Mac 解决了问题。