Search code examples
iosswiftwatchkitios-app-group

Does openParentApplication:reply require App Groups capability to be enabled?


I am developing an app that communicates between the watch and the iOS parent app. It sends data from the WatchKit extension to the parent application by opening it. I understand that openParentApplication:reply, when called, opens the iPhone application from the Apple Watch. After that, application:handleWatchKitExtension:reply is called in the app's delegate.

From there you can open a notification to the view controller with:

NSNotificationCenter.defaultCenter().postNotificationName(aName: String, object anObject: AnyObject?)

"aName" is what you can open up in the view conroller with:

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

Here is my code for my interface controller in my WatchKit extension:

//
//  InterfaceController.swift
//  SendColors WatchKit Extension
//
//  Created by Tommy on 12/30/14.
//  Copyright (c) 2014 Tommy. All rights reserved.
//

import WatchKit
import Foundation


class InterfaceController: WKInterfaceController {

var ypo = false

override func awakeWithContext(context: AnyObject?) {
    super.awakeWithContext(context)

    // Configure interface objects here.
}

@IBOutlet weak var redButton: WKInterfaceButton!

@IBOutlet weak var greenButton: WKInterfaceButton!

@IBOutlet weak var blueButton: WKInterfaceButton!

@IBAction func onRedButtonClick() {
    if ypo {
        openParentAppWithColor("Yellow")
    }
    else {
        openParentAppWithColor("Red")
    }
}

@IBOutlet weak var moreButton: WKInterfaceButton!

@IBAction func moreButtonClick() {
    if !ypo {
        ypo = true
        redButton.setTitle("Yellow")
        redButton.setColor(UIColor.yellowColor())
        greenButton.setTitle("Purple")
        greenButton.setColor(UIColor.purpleColor())
        blueButton.setTitle("Orange")
        blueButton.setColor(UIColor.orangeColor())
        moreButton.setTitle("Back")
    }
    else {
        ypo = false
        redButton.setTitle("Red")
        redButton.setColor(UIColor.redColor())
        greenButton.setTitle("Green")
        greenButton.setColor(UIColor.greenColor())
        blueButton.setTitle("Blue")
        blueButton.setColor(UIColor.blueColor())
        moreButton.setTitle("More...")
    }
}

@IBAction func onGreenButtonClick() {
    if ypo {
        openParentAppWithColor("Purple")
    }
    else {
        openParentAppWithColor("Green")
    }
}

@IBAction func onBlueButtonClick() {
    if ypo {
        openParentAppWithColor("Orange")
    }
    else {
        openParentAppWithColor("Blue")
    }
}

override func willActivate() {
    // This method is called when watch view controller is about to be visible to user
    super.willActivate()
}

override func didDeactivate() {
    // This method is called when watch view controller is no longer visible
    super.didDeactivate()
}

private func openParentAppWithColor(color: String) {
    if ["color": color] != nil {
     if   !WKInterfaceController.openParentApplication(["color": color], reply: { (reply, error) -> Void in
            println(reply)
     }) {
            println("ERROR")
        }
    }
}
}

My problem is that say for instance I clicked the red button on the watch simulator. The action would be called and in that action it calls openParentApplicationWithColor("Red") which would call WKInterfaceController.openParentApplication(["color": color], reply: { (reply, error) -> Void in }) What this is supposed to do is open the parent app on the simulator. It opens it in the background. I, therefore open it manually. When I open the app manually, the background is completely black.
I suspect the problem is that I did not enable App Groups in the Capabilities tab. In order to do that, you need to be in the developer program. Should I join it to do this, or is there another problem? I am using Xcode 6.2 Beta 3. Thank you all in advance!


Solution

  • I have tested and can confirm that openParentApplication:reply: does not require App Groups to be enabled.

    I understand that openParentApplication:reply, when called, opens the iPhone application from the Apple Watch.

    This method opens the iPhone app in the background. In previous betas of Xcode 6.2 the app did open in the foreground, but this was not the intended behaviour and is not how the WatchKit Extension-iPhone app communication will work in the shipping version.

    You can still launch the iPhone app in the foreground manually, but this isn't necessary unless you want to test the use case of both being used at once. At least with the API currently available, the iPhone app it can't be launched programmatically by the watch app to the foreground, and the watch app can't be launched programmatically by the iPhone app.

    Once the app launches, you've reported the screen is still black when you expect it to change colour based on the message you've sent it. Is application:handleWatchKitExtension:reply: being called in the iPhone app? You will know it is definitely being called if you are receiving the reply block back for execution in your WatchKit Extension, which should be outputting something from your println(reply). If so, then the issue is with the code in the iPhone app to do something with the message you've passed to it. It would be useful to see your implementation of that method in your AppDelegate of the iPhone app. (Note if that method failed to call the reply block, it might still be receiving the message and you wouldn't get the reply, but then you would be seeing an error message about the reply not being received.)

    Note that you won't see NSLog messages or get breakpoints in Xcode when running the Watch extension initially, but you can select Debug > Attach to process > [select your iPhone app under 'Likely targets'] and then you will get the logs and breakpoints of the iPhone app instead of the Watch app, while still being able to use the Watch app in the watch simulator. Most useful for debugging.