4

我刚刚使用教程/示例代码在我的应用程序中设置了 WCConnectivity,我觉得我已经正确实现了它。我没有使用模拟器进行测试。出于某种原因,在手表应用程序中没有调用 didReceiveApplicationContext,即使一切设置正确。

我尝试调用 WatchKit 应用程序的接口控制器,在 ExtensionDelegate 中并使用 NSUserDefaults 来设置接口控制器数据。

iOS 应用

视图控制器.m

- (void) viewDidLoad{
if ([WCSession isSupported]) {
    WCSession *session = [WCSession defaultSession];
    session.delegate = self;
    [session activateSession];
  }
}

-(void) saveTrip{
NSMutableArray *currentTrips = [NSMutableArray arrayWithArray:[self.sharedDefaults objectForKey:@"UserLocations"]];

NSData *data = [NSKeyedArchiver archivedDataWithRootObject:newLocation];
[currentTrips addObject:data];
[self.sharedDefaults setObject:currentTrips forKey:@"UserLocations"];
[self.sharedDefaults synchronize];

WCSession *session = [WCSession defaultSession];
NSDictionary *applicationDict = [[NSDictionary alloc] initWithObjects:@[currentTrips] forKeys:@[@"UserLocations"]];;
[session updateApplicationContext:applicationDict error:nil];
}

观看分机代码

ExtensionDelegate.m

- (void)applicationDidFinishLaunching {
if ([WCSession isSupported]) {
    WCSession *session = [WCSession defaultSession];
    session.delegate = self;
    [session activateSession];
}
}
- (void)session:(nonnull WCSession *)session didReceiveApplicationContext:(nonnull NSDictionary<NSString *,id> *)applicationContext {
self.places= [applicationContext objectForKey:@"UserLocations"];
[[NSUserDefaults standardUserDefaults] setObject:self.places forKey:@"UserLocations"];
[[NSUserDefaults standardUserDefaults] synchronize]; 
}

接口控制器.m

- (void)willActivate {
[super willActivate];
self.placesData = [NSMutableArray arrayWithArray:[[NSUserDefaults standardUserDefaults] objectForKey:@"UserLocations"]];
[self loadData];
}
4

4 回答 4

20

对我来说,有两件事:

  1. 在字典中传递无效值。甚至不能传递NSNull()来表示 nil 值。如果那里有无法在 plist 中表示的数据,则会失败。

  2. 如果字典没有改变,后续调用updateApplicationContext不会触发相应的调用didReceiveApplicationContext. 要强制更新(可能在调试版本中),您可以将 UUID 添加到有效负载,例如

    上下文["force_send"] = UUID().uuidString

于 2017-12-20T23:21:52.720 回答
5

处理任何错误可能很有用,因此请更改:

[session updateApplicationContext:applicationDict error:nil];

NSError *error;    
if (![session updateApplicationContext:applicationDict error:&error]) {
    NSLog(@"updateApplicationContext failed with error %@", error);
}
于 2016-03-08T17:24:10.327 回答
2

如果它不起作用,则可能没有正确实施。

乍一看有几个问题:

  • 在您的 iOS 应用程序中,您会获得对共享会话的引用并激活它,但不要将该局部变量分配给视图控制器上的任何属性。viewDidLoad这意味着一旦退出,您的局部变量将超出范围。您还需要在手表扩展程序中更正它。

  • saveTrip中,您再次创建另一个本地会话,该会话未激活且没有任何委托。您需要使用您之前设置和激活的第一个会话。

  • 在您的手表上,您保存接收到的数据,但您的界面控制器不会知道它应该加载和显示新数据。

一些提示:

  • 如果您在 中设置并激活会话application:didFinishLaunchingWithOptions,它将在应用程序范围内可用(并且在应用程序生命周期的早期激活)。

  • 您应该检查您的会话是否有效,因为手表可能未配对,或者可能未安装手表应用程序。这是一个很好的 (Swift) 教程,涵盖了这些情况,并且还使用会话管理器来更轻松地支持在整个应用程序中使用 Watch Connectivity。

  • 您可能希望向手表传递更少/更轻的数据,而不是尝试处理归档自定义对象数组。

  • 顺便说一句,您尝试做的事情NSUserDefaults非常复杂。这实际上是为了在启动过程中保持偏好。滥用它作为在扩展程序和控制器之间来回传递模型的方式是不合适的。

于 2016-03-07T23:35:06.993 回答
1

我有同样的问题并修复。我忘了在手表扩展中添加 WatchConnectivity 框架。

于 2016-06-18T23:08:17.070 回答