4

I have an iPhone application and added a WatchKitExtension. From the iPhone App I want to pass a String to the WatchApp which is supposed to change an image on the Watch.

  • What I already did was to download the source files and import the MMWormhole.m & .h. They are written in Obj-C and so Xcode automatically bridged them for me.
  • I also added an app group and activated it for my WatchExtension & my iPhone target

In the tutorial on GitHub it says I have to initialize the wormhole with:

self.wormhole = [[MMWormhole alloc] initWithApplicationGroupIdentifier:@"group.com.mutualmobile.wormhole"
                                                                          optionalDirectory:@"wormhole"];

...and send a message using:

[self.wormhole passMessageObject:@{@"titleString" : title} 
                         identifier:@"messageIdentifier"];

But I have actually no idea where to put that, I am using Swift in my iPhone application and the WatchExtension.

Can anyone please help me there?

LinusGeffarth
  • 27,197
  • 29
  • 120
  • 174

2 Answers2

5

I suppose it depends on different applications, but for one application I put the listeners in the didFinishLaunchingWithOptions method of my app delegate in the main iOS app. This was because the user would be using the watch, and they would be relaying information off to the phone

There were multiple listeners...

var wormhole = MMWormhole(applicationGroupIdentifier: "group", optionalDirectory: nil)

wormhole.listenForMessageWithIdentifier("identifier", listener: { (message) -> Void in
                //do stuff
})

wormhole.listenForMessageWithIdentifier("identifier2", listener: { (message) -> Void in
            //do stuff
})

wormhole.listenForMessageWithIdentifier("identifier3", listener: { (message) -> Void in
            //do stuff
})

And then in a WKInterfaceController, I sent a message. Sometimes in an action, sometimes in the willActivate method. It really depends on the flow of your app

var wormhole = MMWormhole(applicationGroupIdentifier: "group", optionalDirectory: nil)
    @IBAction func buttonPushed(){            
        wormhole.passMessageObject("object", identifier: "identifier1")
    }

This can work both ways though, I could have very easily put a listener in my watch which would wait for messages initiated by some Interface Controller on the phone.

prawn
  • 2,643
  • 2
  • 33
  • 49
  • It says it doesn't know `MMWormhole`...I tried to import it into my AppDelegate.swift but when I type `import MMWormhole` or with `.m` or `.h` it says there is no such module. – LinusGeffarth Apr 24 '15 at 16:23
  • If you go to your root project -> Build Settings and search for "Objective-C Briding Header", is the path pointing to the right file? The file should be named something like Projectname-Briding-Header.h. And in this file you have the line `#import "MMWormhole.h"` right? – prawn Apr 24 '15 at 16:47
  • When I search it does not show anything, for any target so I just inserted the file's name. Is that right or do I need the file's path? Oh and I added `#import "MMWormhole.h"` but it still does not work :/ – LinusGeffarth Apr 24 '15 at 16:53
  • Hmm. There's no objective c briding header specification? Try looking at this. This link helped me when I couldn't call obj c code in swift. http://stackoverflow.com/questions/24002369/how-to-call-objective-c-code-from-swift – prawn Apr 24 '15 at 17:03
  • No idea what happened and what actually solved it but I added, deleted, imported, removed, readded, etc. and somehow it does work now. Your solution was helpful and thanks for the code translation. – LinusGeffarth Apr 24 '15 at 17:20
  • I have similar problem. When I bridge, I've no problem to use MMWormhole in iphone app, but get complains in the WatchKit Extension. see here: http://stackoverflow.com/questions/30828354/get-unresolved-identifier-for-mmwormhole-in-watch-interfacecontroller-swift – murvinlai Jun 14 '15 at 18:22
5

Here are my instructions. Hopefully they help you with the simplest use case and then you can expand from there. (Remember to structure your code so that it actually makes sense!)

  • Get MMWormhole (the .h and the .m) added to your project. If you know how to use Cocoapods, do that, but otherwise, just use git submodules. (I use git submmodules)
  • Because you need the .h to be visible from Swift, you need to use a bridging header.
  • Set up an App Group, which requires using the Developer Portal. Link is here
  • In your iPhone build target -> Capabilities -> App Groups and add your group. If all three checkboxes do not go perfectly, go back to the Developer Portal and make sure everything is right or start again.

MMWormhole, iPhone Side

Set up the wormhole somewhere you can reach it. NOTE: your group ID has to be the one from above!

let wormhole = MMWormhole(applicationGroupIdentifier: "group.testMe.now", optionalDirectory: nil)
wormhole.listenForMessageWithIdentifier("wormholeMessageFromWatch", listener: { (message ) -> Void in
    if let messageFromWatch = message as? String {
          // do something with messageFromWatch
    }
})

iPhone App Sends String

wormhole.passMessageObject("message from phone to watch", identifier: "wormholeMessageFromPhone")

iPhone app registers to receive and sends again in the callback via MMWormhole (asynchronous but cool)

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
    universe.initWormhole(.phone, messageHandler: { (message) -> () in
        universe.wormhole.passMessageObject("the phone got \(message)", identifier: "wormholeMessageFromPhone")
    })
    return true
}

MMWormhole, Apple Watch Side

Set up the wormhole somewhere you can reach it. NOTE: your group ID has to be the one from above!

let wormhole = MMWormhole(applicationGroupIdentifier: "group.testMe.now", optionalDirectory: nil)
wormhole.listenForMessageWithIdentifier("wormholeMessageFromPhone", listener: { (message ) -> Void in
    if let messageFromPhone = message as? String {
          // do something with messageFromPhone
    }
})

MMWormhole, watch app registers to receive

override func awakeWithContext(context: AnyObject?) {
    super.awakeWithContext(context)
    universe.initWormhole(.watch, messageHandler: { (message) -> () in
        println("MMWormhole Message Came to Watch: \(message)")
    })
}

MMWormhole, watch app sends

// force open the parent application because otherwise the message goes nowhere until the app is opened
WKInterfaceController.openParentApplication(["":""], reply: nil) 
universe.wormhole.passMessageObject("[from watch to phone]", identifier: "wormholeMessageFromWatch")
Dan Rosenstark
  • 68,471
  • 58
  • 283
  • 421