iPhone не получает приложение Context от AppleWatch
Я создал программу для проверки отправки данных назад и вперед с iPhone и AppleWatch, и наоборот. Я настроил его, чтобы на AppleWatch была кнопка, а на iPhone - кнопка. Когда iPhone один нажат, он отправит данные и переименует кнопку на AppleWatch в любую строку данных.
Затем я применил тот же код для AppleWatch для iPhone, но по какой-то причине iPhone, похоже, не получает данные. Вот код для iPhone:
// ViewController.swift
import UIKit
import Foundation
import WatchConnectivity
class WatchManager: UIViewController, WCSessionDelegate {
var watchSession: WCSession? {
didSet {
if let session = watchSession {
session.delegate = self
session.activate()
}
}
}
override func viewDidLoad(){
super.viewDidLoad()
watchSession = WCSession.default
}
private func sendDict(_ dict: [String: Any]) {
do {
try self.watchSession?.updateApplicationContext(dict)
} catch {
print("Error sending dictionary \(dict) to Apple Watch!")
}
}
@IBOutlet weak var transferButton: UIButton!
@IBAction func dataTransfer(_ sender: Any) {
sendDict(["DataKey": UUID().uuidString])
print("sent")
}
func session(_ session: WCSession, activationDidCompleteWith activationState: WCSessionActivationState, error: Error?) {
print("Session activation did complete")
}
public func sessionDidBecomeInactive(_ session: WCSession) {
print("session did become inactive")
}
public func sessionDidDeactivate(_ session: WCSession) {
print("session did deactivate")
}
func session(_ session: WCSession, didReceiveApplicationContext applicationContext: [String : Any]) {
print("phone received app context: ", applicationContext)
if let temperature = applicationContext["DataKey"] as? String {
self.transferButton.setTitle(temperature, for: .normal)
}
}
}
и AppleWatch:
// InterfaceController.swift
import WatchKit
import Foundation
import WatchConnectivity
class InterfaceController: WKInterfaceController {
var watchSession: WCSession? {
didSet {
if let session = watchSession {
session.delegate = self
session.activate()
}
}
}
@IBOutlet weak var temperatureLabel: WKInterfaceButton!
private func sendDict(_ dict: [String: Any]) {
do {
try self.watchSession?.updateApplicationContext(dict)
} catch {
print("Error sending dictionary \(dict) to iPhone!")
}
}
@IBAction func button() {
let urg = ["DataKey":UUID().uuidString]
sendDict(urg)
print("watch sent app context \(urg)")
}
}
extension InterfaceController: WCSessionDelegate {
#if os(iOS)
public func sessionDidBecomeInactive(_ session: WCSession) { }
public func sessionDidDeactivate(_ session: WCSession) {
session.activate()
}
#endif
func session(_ session: WCSession, activationDidCompleteWith activationState: WCSessionActivationState, error: Error?) {
print("Session activation did complete")
}
func session(_ session: WCSession, didReceiveApplicationContext applicationContext: [String : Any]) {
print("watch received app context: ", applicationContext)
if let temperature = applicationContext["DataKey"] as? String {
self.temperatureLabel.setTitle(temperature)
}
}
override func willActivate() {
// This method is called when watch view controller is about to be visible to user
super.willActivate()
watchSession = WCSession.default
}
override func didDeactivate() {
// This method is called when watch view controller is no longer visible
super.didDeactivate()
}
}
Я попытался изменить имя ключа (не сработало), я сделал так, чтобы значение данных всегда менялось (UUID(). UuidString), и сохранил его. Другие вещи, которые я пробовал, состояли в создании ярлыка и попытке переименовать его вместо кнопки, которая не работала, и, наконец, вместо переименования кнопки, просто отправив подтверждение того, что она получила данные обратно в часы Apple, что не удалось.
Любая помощь будет высоко ценится, я надеюсь, что это не глупая ошибка.
2 ответа
Я думаю updateApplicationContext
это не правильный метод для ваших нужд. Из документов:Система отправляет контекстные данные, когда появляется такая возможность, с целью подготовить данные к использованию ко времени пробуждения партнера. Если вы хотите отправлять данные туда и обратно, пока оба приложения находятся на переднем плане sendMessage
должно сработать.
В конце вам может потребоваться реализовать комбинацию обоих методов. Я предлагаю прочитать следующий документ: https://developer.apple.com/documentation/watchconnectivity/wcsession
Редактировать:
Просто чтобы прояснить ситуацию с "В конце концов, вам может понадобиться реализовать комбинацию обоих методов", я еще добавил пример кода из одного из моих приложений.
Метод _sendData
пытается отправить текущие данные через sendMessageData
, если часы достижимы. Если нет, обновляется контекст приложения, чтобы данные были доступны, как некоторые, при запуске приложения наблюдения.
- (void)_sendCurrentData
{
if ([WCSession defaultSession].isPaired && [WCSession defaultSession].isWatchAppInstalled)
{
if ([WCSession defaultSession].isReachable)
{
// Send data to watch
[[WCSession defaultSession] sendMessageData:self.currentData
replyHandler:nil
errorHandler:^(NSError * _Nonnull error) {
[self _updateApplicationContext];
}];
}
else
{
[self _updateApplicationContext];
}
}
}
- (void)_updateApplicationContext
{
if ([WCSession defaultSession].isPaired && [WCSession defaultSession].isWatchAppInstalled)
{
NSError* error = nil;
[[WCSession defaultSession] updateApplicationContext:@{@"data": self.currentData}
error:&error];
if (error != nil)
{
NSLog(@"error while updating application context: %@", error.localizedDescription);
}
}
}
use self.watchSession?.transferUserInfo(dict) instead of self.watchSession?.updateApplicationContext(dict)
you'll got a call back in:
func session(_ session: WCSession, didReceiveUserInfo userInfo: [String : Any] = [:]) {
}