0

I couldn't find an easy way to update the view in my iPhone app when I push a button on the AppleWatch App yet.

I tried it with NSUserDefaults Observer like this:

iPhone App Viewcontroller(inside ViewDidLoad()):

 // Create and share access to an NSUserDefaults object.
 mySharedDefaults = NSUserDefaults(suiteName: "group.sharedTest")

//Add Observer    
NSUserDefaults.standardUserDefaults().addObserver(self, forKeyPath: "test", options: NSKeyValueObservingOptions.New, context: nil)

In the Watchkit Extensions InterfaceController I added an IBAction with the button with this code:

mySharedDefaults!.setObject("testValue", forKey: "test")
mySharedDefaults!.synchronize()

But when I press the button, nothing happens! If I set an object inside my iPhone ViewController it works, but not if it is updated via the app! Can someone help me?

iVentis
  • 993
  • 6
  • 19

2 Answers2

2

You weren't lucky because when you wrote your question there wasn't API for this in iOS SDK. Three days ago, 10th December 2014 Apple released iOS 8.2 beta 2 SDK with two, important for this task, methods.

In WatchKit Framework, WKInterfaceController class

// Obj-C
+ (BOOL)openParentApplication:(NSDictionary *)userInfo
                        reply:(void (^)(NSDictionary *replyInfo,
                                        NSError *error))reply

By calling this method iOS will run your app in the background and AppDelegate of app will receive this message

- (void)application:(UIApplication *)application handleWatchKitExtensionRequest:(NSDictionary *)userInfo reply:(void(^)(NSDictionary *replyInfo))reply. 

This is second method added in iOS SDK Beta 2 (in terms of this question) in UIKit Framework, UIApplicationDelegate class.

You can use NSDictionary and reply block to communicate Watch app and iOS app.

Example

In your WKInterfaceController subclass

- (IBAction)callPhoneAppButtonTapped
{
    NSDictionary *dictionary = [[NSDictionary alloc] initWithObjectsAndKeys:@"text to display", @"key", nil];

    [InterfaceController openParentApplication:dictionary reply:^(NSDictionary *replyInfo, NSError *error) {
        NSLog(@"Reply received by Watch app: %@", replyInfo);
    }];
}

and then in your iOS AppDelegate class

- (void)application:(UIApplication *)application handleWatchKitExtensionRequest:(NSDictionary *)userInfo reply:(void (^)(NSDictionary *))reply
{
    NSLog(@"Request received by iOS app");
    NSDictionary *dictionary = [[NSDictionary alloc] initWithObjectsAndKeys:@"your value to return to Apple Watch", @"key", nil];

    reply(dictionary);
}

When you tap button on Apple Watch simulator your iOS app in iOS Simulator will be launched, and you should be able to see NSLog's in proper places.

Note

This solution works for transporting objects between Watch and iOS apps. But if you plan to transport more data, access images, file etc, you should use Shared app group. You set shared app group in Capabilities in your Xcode Project file. Use containerURLForSecurityApplicationGroupIdentifier (NSFileManager class) to get URLs to files in shared group.

If you want to share Preferences initWithSuiteName from NSUserDefaults is what you are looking for.

lvp
  • 2,078
  • 18
  • 24
  • Thank you very much for your very interesting update information!! I will try this asap! Unfortunate I have not enough reputation yet to upvote your answer! I'm sorry! – iVentis Dec 13 '14 at 22:51
  • 1
    I didn't have time to test it yet! I'll tell you as soon as I find time ;) – iVentis Dec 14 '14 at 07:46
  • This works but only problem is that I am not able to see the NSLog from iPhone app (the iPhone app is doing what it was asked to do, just that I cannot see logs from it). – Sumit Nathany Mar 20 '15 at 12:01
  • @SumitNathany unfortunately I had the same problem with NSLog, looks like Xcode issue. – lvp Mar 21 '15 at 09:00
  • The NSLog should come only when you attached the iOS app as a process in debug section. Usually, I will see all NSLogs which are in extension, but attaching the Iphone app as process, the Xcode shows the debug logs. – Balram Tiwari May 08 '15 at 12:17
0

I am guessing that the WatchKit extension app, and your iPhone app, are separate running application instances, and that notifications are for within the same instance.

As an alternative, perhaps you could have a new operation in a separate thread on the iPhone app that regularly checks for changes to particular keys, and produces a notification itself when it detects that change.

saward
  • 429
  • 1
  • 6
  • 14
  • I don't think you need an operation to do that. Why don't post a local notification from the extension app. The iPhone app can receive the notification and let you continue the works. Just remember to remove the notification from NotificationCenter after receiving it otherwise user may see it in NotificationCenter. – sahara108 Nov 21 '14 at 09:21
  • If notifications between the iPhone app and extension work, then that would be easier. I had thought, because the shared defaults notifications were not working across apps, that notifications in general would not. But if they do, your suggestion is definitely easier. – saward Nov 21 '14 at 12:45
  • 1
    @sahara108 this won't work because extension and host app are two different processes, hence they have different memory pool, hence their NSNotificationCenter defaultCenter are different. – lvp Mar 21 '15 at 08:59