2016-03-07 74 views
2

我刚刚在我的应用程序中使用教程/示例代码设置了WCConnectivity,我觉得我已经正确实施了。我没有使用模拟器来测试。出于某种原因,即使所有设置都正确,didReceiveApplicationContext也不会在手表应用程序中调用。didReceiveApplicationContext不被调用

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

iOS应用

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

有没有名为'didReceiveApplicationWithContext'方法。发布您的实际代码。 – dan

+0

@dan更新了原文 – emleeh

回答

2

如果它不工作,它可能无法正确执行。

第一眼的几个问题:

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

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

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

一些提示:

  • 如果在安装和激活application:didFinishLaunchingWithOptions会议,这将是可用的应用程序范围内(在您的应用程序的生命周期中更早地激活)。

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

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

  • 另一方面,你想要做什么NSUserDefaults是非常复杂的。这实际上意味着在推出期间坚持偏好。将它用作在扩展和控制器之间来回传递模型的方式并不合适。

+0

谢谢。我只是非常自由地使用NSUserDefaults,因为这是应用程序的beta版本,而在实际的应用程序中,我将使用数据库和API调用。我认为这可能与我的实际项目有关 - 即使在关闭Watch App时,我的session.reachable也是如此。我也收到一个错误,表示手表二进制文件没有连接到手表扩展,这又是关系。我可能只需要开始一个新项目并重新设置。 – emleeh

4

它可能被证明是处理任何错误有用的,所以改变:

[session updateApplicationContext:applicationDict error:nil]; 

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

我有同样的问题和解决。 我忘了在Watch扩展中添加WatchConnectivity框架。

0

对我来说,这是两件事情:

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

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