didReceiveApplicationContext未被调用

时间:2016-03-07 21:32:31

标签: ios watchkit watch-os-2 watchconnectivity

我刚刚使用教程/示例代码在我的应用程序中设置了WCConnectivity,我觉得我已经正确实现了它。我没有使用模拟器进行测试。出于某种原因,即使所有内容都已正确设置,也不会在监视应用程序中调用didReceiveApplicationContext。

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

iOS App

ViewController.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]; 
}

InterfaceController.m

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

4 个答案:

答案 0 :(得分:9)

对我来说,这是两件事:

  1. 在字典中传递无效值。甚至无法通过NSNull()来表示nil值。如果您的数据无法在plist中表示,则会失败。
  2. 如果字典未更改,则对updateApplicationContext的后续调用不会触发对didReceiveApplicationContext的相应调用。要强制更新,您可以向有效负载添加UUID,例如

    context["force_send"] = UUID().uuidString
    

答案 1 :(得分:4)

处理任何错误可能有用,所以改变:

[session updateApplicationContext:applicationDict error:nil];

NSError *error;    
if (![session updateApplicationContext:applicationDict error:&error]) {
    NSLog(@"updateApplicationContext failed with error %@", error);
}

答案 2 :(得分:2)

如果它不起作用,可能无法正确实现。

乍一看有几个问题:

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

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

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

一些提示:

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

  • 您应该检查您的会话是否有效,因为手表可能未配对,或者可能未安装手表应用。以下a good (Swift) tutorial that covers those cases, and also uses a session manager可让您更轻松地在整个应用中使用Watch Connectivity。

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

  • 顺便说一句,你试图用NSUserDefaults做的事情非常复杂。这真的意味着在发布之间保持偏好。滥用它作为在扩展和控制器之间来回传递模型的方法是不合适的。

答案 3 :(得分:1)

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