我刚刚使用教程/示例代码在我的应用程序中设置了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];
}
答案 0 :(得分:9)
对我来说,这是两件事:
NSNull()
来表示nil值。如果您的数据无法在plist中表示,则会失败。如果字典未更改,则对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框架。