WatchKit: Open Your iOS App From The Watch

UPDATE: It is NOT currently possible to open your iOS app from the Apple Watch. This was a bug with that version of Xcode, which has since been fixed. See comments for more information or a short explanation of my mistake.

The most exciting part of yesterday’s Xcode 6.2 Beta 2 release was the new added ability to open the iOS app from the Apple Watch and even pass information while doing so! It’s super easy to do.

Here is the simple sample app I built:

As the user clicks on a button in the Watch App, it triggers the opening of the iOS app. Here is how to make this app:

The Setup

Make sure to download XCode 6.2 Beta 2 or up for this to work! If you haven’t gone through the process of making a Hello, World WatchKit app, follow the instructions outlined in my How To Create A “Hello World” WatchKit App post.

The Design

In Interface.storyboard, drag buttons onto the InterfaceController, and change the Button Title Colors as below:

Screen Shot 2014-12-12 at 5.10.34 AM

Create IBActions

For each button, create an IBAction by Control + Dragging each button to the Interface Controller:

Insert_Connection_and_Interface_storyboard_—_Edited

Now comes the fun part!

Open Application

We’re going to use the new openParentApplication:reply: class method on the WKInterfaceController to open our application. Here is the Documentation for it:

Screen Shot 2014-12-12 at 5.23.42 AM

Since all the IBActions will open up the parent app, but send a different color, I created a function they can all call for more DRY code:

InterfaceController_swift_—_Edited

Run your Watch app! Now, when you click on the buttons, it’ll open up your parent iOS app. Of course, the last part is to use the information passed to the parent iOS app to do something (like change background color in this case)…

Handle WatchKit Extension Request

There is now a new method for the App Delegate to handle the WatchKit Extension Request:

AppDelegate_swift

Since we have to handle the WatchKit request in the AppDelegate, my implementation includes just posting a notification, so that any object that depends on the information in the WatchKit request can just handle it as needed.

Now, the iOS app’s ViewController can listen for the notification and change color accordingly:

//  ViewController.swift

import UIKit

class ViewController: UIViewController, UIAlertViewDelegate {

    private enum Color: String {
        case Red = "red"
        case Green = "green"
        case Orange = "orange"
        case Blue = "blue"

        func color() -> UIColor {
            switch self {
            case Red:
                return UIColor.redColor()
            case .Green:
                return UIColor.greenColor()
            case .Orange:
                return UIColor.orangeColor()
            case .Blue:
                return UIColor.blueColor()
            }
        }
    }

    override func viewDidLoad() {
        super.viewDidLoad()

        NSNotificationCenter.defaultCenter().addObserver(self,
            selector: Selector("handleWatchKitNotification:"),
            name: "WatchKitSaysHello",
            object: nil)

    }

    deinit {
        NSNotificationCenter.defaultCenter().removeObserver(self)
    }

    func handleWatchKitNotification(notification: NSNotification) {
        if let userInfo = notification.object as? [String : String] {
            if let colorStr = userInfo["color"] {
                let color = Color(rawValue: colorStr)
                view.backgroundColor = color?.color()
            }
        }
    }

}

That’s it! This is all pretty simple, but think of all the possible interactions this new WatchKit capability allows! I can see lots of fun games taking advantage of this… And this is all only in Beta 2. A lot more to come for sure!

You can view the source code on Github here.

Enjoy the article? Join over 14,500+ Swift developers and enthusiasts who get my weekly updates.

  • Aaron Brager

    Thanks for posting this. One suggestion: if you’re removing the observer in viewDidDisappear, it should be registered in viewDidAppear, not viewDidLoad. Otherwise the notification won’t be received if the user leaves and reenters the iPhone app.

    Alternatively, you could unregister in the deinit function.

    • Good point. Updated. Got thrown off by the deprecation of ViewDidUnload.

  • Thanks for your demo,but I saw watch app cant open host app, it is only happened in simulator,not on real iPhone yet,do you have any idea?

    • This is an official WatchKit API, so this will work on the real Watch / iPhone…

      • https://devforums.apple.com/thread/257015?tstart=15 It seems like a bug….do you have time ti check it ? Thanks a lot.

      • Hi Natasha! Like Jerry Liu says, it (seems) like a bug. The documentation says that this API opens main app on the background to do tasks, and that the app shouldn’t be opened on the foreground.

        I’ve also read that if the iPhone is unlocked, it will open the app on the foreground. But it doesn’t work on the simulator. So it seems like it’s a bug on the simulator. 🙂

        • Thanks, good to know!

          • Sarath Sasi

            any one can help me to update instantly from the parent app (iPhone App) and Show the value in the watch App. I have to reload the value in the watch screen when ever the apps values get updated

  • fbara

    Is anyone else having a the problem where ViewController.swift isn’t being called when the iPhone app opens? I was having problems getting my background color to change so I set a few breakpoints in ViewDidLoad and ViewDidDisappear. I wanted to see if my function that changes the color was getting called. The breakpoints were never hit.

    I opened Natasha’s code and set the same breakpoints (this code is for the next tutorial, however). Those breakpoints weren’t called either, however her background color was changing. I searched all the code for view.backgroundcolor and it only shows up in ViewController.swift. Now I’m a bit confused as to what’s going wrong.

  • senior

    Hi, just a note that on a real Apple Watch, this will not actually open the application on the iPhone. The iPhone app will only process the message in the background.

    • Good to know… Do you have a link or anything from Apple that says this? Not surprised – I’m guessing things will not be working as smoothly with the real hardware.

      • senior

        Yes, an Apple developer posted it in the dev forums here: https://devforums.apple.com/message/1082614#1082614

        • John Zuo

          I use another way to realized.You can like this:

          if ([ourApplication canOpenURL:ourURL]) {

          [ourApplication openURL:ourURL];
          }

          apps open self.More question can add my skype: zuo.cun

  • Gags

    Hello Natasha, openParentApplication() will not open the host app in foreground. I have checked it in simulator which contradicts the video. Are you sure we can open the host app from the watch app? Is this possible?

    • It worked for me in the Simulator, and it sounds like that’s possible from the name of the method: openParentApplication, but looks like it’s actually not possible from the comments below. Will have to try it out with the actual hardware…

  • hlpdt10

    we couldn’t use the line WKInterFaceController.openParentApplication
    in xcode 6 beta 3. How can we open the parent Application now?

  • Maher Rezeq

    There is a limitation to open the application from the watch but I found a hack where you can use inside the handleWatchKitExtensionRequest to open the application from custom URL

    [[UIApplication sharedApplication] openURL:[NSURL URLWithString:yourAppURL]];

  • Spooky Mormon Hell Dream

    Let’s be very clear here. openParentApplication does NOT open your iOS app into the foreground, which means you can’t present any UI unless your app was already active. LAME!

    • Yaaashua

      Yea 🙂 I got excited when I saw the video and I was wondering what did I do wrong cuz mine doesnt open. Then I saw the documentation:
      “Calling the method causes iOS to launch the app in the background (as needed)”
      and I wonder when does “(as needed)” means exactly.
      – And Why her application actually opens? mine doesn not open even being active 🙁

    • In the beta I was using, there was a bug where it actually did open the application into the foreground. But unfortunately it does NOT actually and the bug has been fixed. It should be used to trigger a background task if needed.

  • juni0r

    tried with XCode Version 6.2 (6C131e) . doesn’t work.

  • vanylapep

    Maybe this is a lame question but, how come for the openParentApplication, the reply block has [:]!, NSError! as parameters but the for handleWatchKitExtensionRequest, reply block has no NSError! parameter? How do you send back an error then? And where does the NSError from openParentApplication comes from? Thanks!

  • Jagaa

    @natashatherobot:disqus How can finish watch app when parent app is exited?
    I couldn’t find about how exit app in watch app programmitcally… 🙁

  • Sarath Sasi

    any one can help me to update instantly from the parent app (iPhone App)
    and Show the value in the watch App. I have to reload the value in the
    watch screen when ever the apps values get updated. Exactly opposite of this topic. I have to update from the app and show it in its extension app

  • Jeeth

    I had a question; Is it possible to call a number from the interface controller?
    Can anyone help on this

  • I think this is no longer working with Watch OS 2.

  • Shoaib Aslam

    I have a button in my Phone App which when tapped should call a method on watch app and it is working fine when watch app is in foreground. But when watch app is in background or not running how can I call its method from Phone app. Any suggestions plz