Code Monkey home page Code Monkey logo

mmwormhole's Introduction

MMWormhole

MMWormhole creates a bridge between an iOS or OS X extension and its containing application. The wormhole is meant to be used to pass data or commands back and forth between the two locations. Messages are archived to files which are written to the application's shared App Group. The effect closely resembles interprocess communication between the app and the extension, though true interprocess communication does not exist between extensions and containing apps.

The wormhole also supports CFNotificationCenter Darwin Notifications in an effort to support realtime change notifications. When a message is passed to the wormhole, interested parties can listen and be notified of these changes on either side of the wormhole. The effect is nearly instant updates on either side when a message is sent through the wormhole.

Example App

Example

[self.wormhole passMessageObject:@{@"buttonNumber" : @(1)} identifier:@"button"];

[self.wormhole listenForMessageWithIdentifier:@"button" 
  listener:^(id messageObject) {
    self.numberLabel.text = [messageObject[@"buttonNumber"] stringValue];
}];

Getting Started

Note

The MMWormhole Example app will only work with your shared App Group identifiers and Entitlements and is meant purely for reference


Installing MMWormhole


You can install Wormhole in your project by using CocoaPods:

pod 'MMWormhole', '~> 2.0.0'

Carthage compatible
MMWormhole also supports Carthage.

Overview

MMWormhole is designed to make it easy to share very basic information and commands between an extension and it's containing application. The wormhole should remain stable whether the containing app is running or not, but notifications will only be triggered in the containing app if the app is awake in the background. This makes MMWormhole ideal for cases where the containing app is already running via some form of background modes.

A good way to think of the wormhole is a collection of shared mailboxes. An identifier is essentially a unique mailbox you can send messages to. You know where a message will be delivered to because of the identifier you associate with it, but not necessarily when the message will be picked up by the recipient. If the app or extension are in the background, they may not receive the message immediately. By convention, sending messages should be done from one side to another, not necessarily from yourself to yourself. It's also a good practice to check the contents of your mailbox when your app or extension wakes up, in case any messages have been left there while you were away.

MMWormhole uses NSKeyedArchiver as a serialization medium, so any object that is NSCoding compliant can work as a message. For many apps, sharing simple strings, numbers, or JSON objects is sufficient to drive the UI of a Widget or Apple Watch app. Messages can be sent and persisted easily as archive files and read later when the app or extension is woken up later.

Using MMWormhole is extremely straightforward. The only real catch is that your app and it's extensions must support shared app groups. The group will be used for writing the archive files that represent each message. While larger files and structures, including a whole Core Data database, can be shared using App Groups, MMWormhole is designed to use it's own directory simply to pass messages. Because of that, a best practice is to initialize MMWormhole with a directory name that it will use within your app's shared App Group.

Initialization

Initialize MMWormhole with your App Group identifier and an optional directory name

Objective-C:

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

Swift:

let wormhole = MMWormhole(applicationGroupIdentifier: "group.com.mutualmobile.wormhole", optionalDirectory: "wormhole")

Passing a Message

Pass a message with an identifier for the message and a NSCoding compliant object as the message itself

Objective-C:

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

Swift:

wormhole.passMessageObject("titleString", identifier: "messageIdentifier")

Reading a Message

You have two options for reading a message. You can obtain the message for an identifier at any time by asking the wormhole for the message.

Objective-C:

id messageObject = [self.wormhole messageWithIdentifier:@"messageIdentifier"];

You can also listen for changes to that message and be notified when that message is updated.

Objective-C:

[self.wormhole listenForMessageWithIdentifier:@"messageIdentifier" 
 listener:^(id messageObject) {
    // Do Something
}];

Swift:

wormhole.listenForMessageWithIdentifier("messageIdentifier", listener: { (messageObject) -> Void in
    if let message: AnyObject = messageObject {
        // Do something
    }
})

Designing Your Communication Scheme

You can think of message passing between apps and extensions sort of like a web service. The web service has endpoints that you can read and write. The message identifiers for your MMWormhole messages can be thought of in much the same way. A great practice is to design very clear message identifiers so that you immediately know when reading your code who sent the message and why, and what the possible contents of the message might be. Just like you would design a web service with clear semantics, you should do the same with your wormhole messaging scheme.

Communication with WatchConnectivity

The design of your communication scheme is even more important when you need to support watchOS 2. MMWormhole supports the WatchConnectivity framework provided by Apple as an easy way to get up and running quickly with a basic implementation of WatchConnectivity. This support is not intended to replace WatchConnectivity entirely, and it's important to carefully consider your watch app's communication system to see where MMWormhole will fit best.

Here are two things you need to know if you want to use WatchConnectivity support in your app:

  • MMWormholeSession is a singleton subclass of MMWormhole that supports listening for WatchConnectivity messages. It should be used as the listener for all MMWormhole messages you expect to receive from the WatchConnectivity framework. Be sure to activate the session once your listeners are set so that you can begin receiving message notifications.

  • Use the MMWormholeSessionTransiting types described below when creating your wormholes, but be careful not to send too many messages at once. You can easily overload the pipeline by sending too many messages at once.

Message Transiting Options

The mechanism by which data flows through MMWormhole is defined by the MMWormholeTransiting protocol. The default implementation of the protocol is called MMWormholeFileTransiting, which reads and writes messages as archived data files in the app groups shared container. Users of MMWormhole can implement their own version of this protocol to change the message passing behavior.

There are three new implementations of the MMWormholeTransiting protocol that support the WCSession application context, message, and file transfer systems. You may only use one form of transiting with a wormhole at a time, so you need to consider which type of messaging system best fits a given part of your application.

Most apps will find the application context system to be a good balance between real time messaging and simple persistence, so we recommend MMWormholeSessionContextTransiting as the best place to start. Check out the documentation and header comments for descriptions about the other messaging types.

You can get started quickly with a wormhole using one of the built in transiting types by calling the optional initializer to set up an instance with the right transiting type for your use case.

Objective-C:

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

Swift:

let wormhole = MMWormhole(applicationGroupIdentifier: "group.com.mutualmobile.wormhole", 
								   optionalDirectory: "wormhole",
								      transitingType: .SessionContext)

Requirements

MMWormhole requires iOS 7.0 or higher or OS X 10.10 or higher. MMWormholeSession requires iOS 9.0 or higher.

Troubleshooting

If messages are not received on the other end, check Project->Capabilities->App Groups.
Three checkmarks should be displayed in the steps section.

Correct App Group Capabilities

Incorrect App Group Capabilities

Credits

MMWormhole was created by Conrad Stoll at Mutual Mobile.

Credit also to Wade Spires, Tom Harrington, and Rene Cacheaux for work and inspiration surrounding notifications between the containing app and it's extensions.

License

MMWormhole is available under the MIT license. See the LICENSE file for more info.

mmwormhole's People

Contributors

chrisfsampaio avatar cnstoll avatar confusedvorlon avatar edelabar avatar ehtd avatar fadhelchaabane avatar felixlam avatar gcox avatar ghecho avatar hiddenjester avatar icodesign avatar jadquincyjohn avatar martinblech avatar mattsson avatar naldikt avatar natemcguire avatar orta avatar sejas avatar tomguthrie avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

mmwormhole's Issues

iOS & OS X

Hello

It is possible to pass data between an app of OS X and app iOS?

Is it possible to call a method from parent app?

I want to call a method (which is inside a controller into the main app) directly from applewatch.
I mean..I click a button on the applewatch and the app on the iPhone starts do something.
Is this possible using MMWormhole?

Thanks

installation with CocoaPods and use_frameworks! not working in WatchKit extension

I try to install MMWormhole with cocoapods in my project (mixed Objective-C / Swift)

platform :ios, '8.0'

inhibit_all_warnings!

use_frameworks!

target 'MyApp' do
    pod 'MMWormhole', '2.0.0'
end

target 'kontoalarm WatchKit Extension' do
    pod 'MMWormhole', '2.0.0'
end

In the bridging header I include MMWormhole as well:

#import <MMWormhole/MMWormhole.h>

But when using it in swift-files of my WatchKit-extension I get

Use of unresolved identifier 'MMWormhole'

Am I missing something?

read messageObject when iOS app isn't in background

Hi
Thank you for your incredible work !
i would like to know if is possible to read the message object send from the watch app when the iOS app isn't in back ground .
For example : the iOS App is closed , i open the watch app and send the message object .
If is possible, where i must put my listenForMessageWithIdentifier code to read the message object ?
In my appdelegete or in my view controller ?

Thank you so much

Vanni

messageWithIdentifier not working on iOS 9 and watchOS 2 simulator

Hello, i'm struggling with a problem in my project, i cannot pass data from my iOS app to watchOS app extension, messageWithIdentifier always return nil and listenForMessageWithIdentifier is never trigged. All settings seem to be ok. App group, entitlements keys, all seems fine, i double checked every setting in all targets.

Anyone have any idea of what could be causing the problem? Simulator issues maybe?

Values are not passed, if i download the file and simulate it

If i download the file and import the xcodeproject in xcode, there are no labels shown.
It doesnt show "one" "two" "three" on the watch and not 1, 2 or 3 on the iphone.
What's the problem here? I haven't changed any code.
It just doesn't work like the gif shows.

Thank you

On simulator..

When i lock device on simulator Apple Watch extension don't work, can i use MMWormhole to send data or to make request to iPhone when app is in background mode ?

MMWormhole not receiving messages when the app is launched from glance

The library works fine in the main watch application with WatchOS 2. When you go on the application glance and after you tap on the glance to return in the application, MMWormdhole don't receive any message from the iPhone (iOS 9). it's necessary to make a force touch to show the application menu and after, quit the menu to reactivate MMWormhole. After that, it works fine.
This problem exists only on the watch. There is no problem on the simulator.
Any ideas of the problem ?

1.3.0 does not follow semantic versioning

I was using 1.2.0 in a project built against watchOS 1 (iOS SDK 8.4). For a number of reasons, my company has not yet switched to Xcode 7 and watchOS 2, though we will be in the near future.

I recently updated our pods, using an optimistic version of MMWormhole ~> 1.1, which updated us from 1.2 to 1.3 and broke our build due to the dependency on WatchConnectivity, which does not exist in the 8.4 SDK.

Proper semantic versioning would dictate that breaking API changes result in a new major version of the library, i.e. 2.0.0. If the version is to remain at 1.3.0 I would suggest that you add in compatibility checks to not use WatchConnectivity when building for an SDK version less than 9.0.

Thanks!

listener is not called in my setup

i am having an issue with receiving messages. both app & extension (watchkit) share the same group identifier.

i have the main app's wormhole on its appdelegate (is this good practice?) and the code looks like this:

self.wormhole = [[MMWormhole alloc] initWithApplicationGroupIdentifier:GROUP_IDENTIFIER
                                                     optionalDirectory:GROUP_WORMHOLE_DIR];

// Listen for changes to the selection message. The selection message contains a string value
// identified by the selectionString key. Note that the type of the key is included in the
// name of the key.
[self.wormhole listenForMessageWithIdentifier:GROUP_WORMHOLE_KEY listener:^(id messageObject) {
    NSLog(@"wormhold called");
    NSString *message = (NSString *)messageObject[@"message"];
    if(message != nil){
        NSLog(@"received wormhole message");
    }
}];

and in the extension:

_wormhole = [[MMWormhole alloc] initWithApplicationGroupIdentifier:GROUP_IDENTIFIER
                                                     optionalDirectory:GROUP_WORMHOLE_DIR];

[_wormhole passMessageObject:@{@"message" : @"supermessage"} identifier:GROUP_WORMHOLE_KEY];

for some reason however the listener is never triggered. is this an issue of iOS 8.2 maybe?

Make listener callback more scalable

Hi! At the moment lister called with only one object 'messageObject' and MMWormhole allows only one listener for identifier. To make implementation more scalable: several listeners can be registered for one identifier; one block can be used to listen for several identifiers - just add additional argument to the listener "identifier:(NSString*)identifier" this will make life mush easier and will allow to create more robust high level design implementation over MMWormhole

P.S. @cnstoll I'm using currently active MMWormhole 1.1.1

Method "listenForMessageWithIdentifier" didn't work if I launch watch app from glance

Here is an simple example project:

https://github.com/yenchenlin1994/WormholeBugExample

(You have to change App groups to your own groups)

This app simply use a NSTimer to update counter label on Phone interface,
and then use MMWormhole try to sync value of the label on Watch interface.

It works totally fine when I choose schema WormholeBugExample WatchKit App
to run, and then manually open the phone app on iOS simulator.

However, things changed if I change schema to Glance - WormholeBugExample WatchKit App and then do the same process as above.

After I tap on Glance to launch my watch app, the label on watch's interface didn't correctly sync with label on phone interface.

In fact, it sometimes stop listening for the message at the beginning or when counter counts to particular value (ex: When it counts to 8).

How can I fix it?

Message Transiting Options

Hello!

I'm using the cordova-plugin-apple-watch from leecrossley and had to find out how this plugin is working on terms of your MMWormhole implementation. Now I am in the situation i wish to use different Message Transiting Options. As default the plugin is using "MMWormholeSessionContextTransiting" and i am quite satisfied with it. But i need a "MMWormholeSessionMessageTransiting" in special situations (e.g. letting the iPhone make a URLReqeuset in background) as well. Now i am bothering around how two handle these two Transiting Options since they are set in the initialization phase. Is there any use case or best practice?

library not found for -lMMWormhole

ld: warning: directory not found for option '-L/Users/Desktop/testbridge/platforms/ios/build/Debug-iphoneos' ld: library not found for -lMMWormhole clang: error: linker command failed with exit code 1 (use -v to see invocation)

Swift

Any plans to write this in Swift? This is the only dependency I have that requires I create a bridging header in my project to get Objective-C support.

Queueing messages, instead of saving only the most recent one

Any plans to support storing the sequence of messages in the order they were posted, so if an extension posts many of them while the app is away then they all can be received on the next launch?

If you have no plans to do this, then do you have any suggestions for me while implementing that myself in a way that you'd accept in a pull request? Should I add separate methods queueMessageObject:identifier: queuedMessageWithIdentifier:? Or, what I'm preferring, should there be boolean property that can be turned on for a MWWormhole which changes the semantics of the existing methods?

Regarding those semantics, presumably messageWithIdentifier: would remove the oldest message passed to the wormhole and return it, or return nil if none, so that it can be called repeatedly to get all of them.

The listener block would be called upon notification as before, passing in the message, which gets automatically removed from the queue. But if the other side hasn't pulled out all the preceding messages yet, then this message will be received out of order. I'm thinking that the listener should have the option of making explicit calls to messageWithIdentifier: to catch any that its missed, where the passed-in object would presumably be at the end of those results. (I'm considering the case where the app polls for stored messages on launch then sets up the listener afterwards, and how to ensure any messages sent during that gap are received in order). Its seems that the notification code that calls the listener needs to initially leave its message in the queue, then be wary of it possibly getting removed "behind its back" once the listener returns.

At the moment, I'm not sure what would be expected if once side turns on queueing and the other doesn't, but I'm sure some reasonable behavior can be chosen.

Lastly, I was originally wanting to add support for this just by subclassing MWWormhole, but I believe there's no way to make that work well. If you think I'm wrong about that please let me know.

Passing data while either app is inactive?

Hey guys I'm using WatchOS 2 and iOS 9

My app has a timer that runs for a user defined amount of time, which can get pretty dangerous with background tasks and I'm worried about asking apple to approve an app that could potentially drain the users battery, which is why I use a local notifications instead of a background mode.

I'm now working in my watch app with WatchOS2 and I'm running into an updating issue where if I wake the watch and ping the phone app isn't responding back because it's asleep, and if the user doesn't have their watch app open while the iPhone app is sending it updates, it's not receiving them and updating the UI...

So here's what I'm wondering, is there anyway for maybe just the watchOS app to continue to get those updates from the iPhone even if it is not awake? It is using a workout session so it's always the forefront of the app. I'm just trying to make sure I'm not missing something before I attempt to dive into this a different way and possibly make more time.

Thanks! (2.0 has been splendid so far by the way amazing work!)

Lower deployment target

Is this necessary to use iOS 8.0 deployment target?

There are no iOS8 only methods used in this code, so it can be probably used in projects for iOS 7.0

Principles working

Hello, I'm inexperienced at MMWormhole and I'm here to do a questions. I see that MMWormhole creates a bridge between an iOS or OS X extension so it's used to pass data or commands back and forth between the two locations.
Now I'm reading on official apple doc that there are two way to tell between the apple watch and Its Paired iPhone namely "Sharing Data with Your Containing iOS App" and "Communicating Directly with Your Containing iOS App". Now I've a doubt, what is the difference between this two methods and MMwormhole? This latter is based on one of two methods? I want to understand this library low level. Thanks

Build warning "Unused Entity Issue"

Build warning "Unused Variable appGroupContainer" on MMWormholeFileTransiting.m:55

- (void)checkAppGroupCapabilities {
    NSURL *appGroupContainer = [self.fileManager containerURLForSecurityApplicationGroupIdentifier:self.applicationGroupIdentifier];
    NSAssert(appGroupContainer != nil, @"App Group Capabilities may not be correctly configured for your project, or your appGroupIdentifier may not match your project settings. Check Project->Capabilities->App Groups. Three checkmarks should be displayed in the steps section, and the value passed in for your appGroupIdentifier should match the setting in your project file.");
}

iPhone 4S Crash

Currently if you use MMWormHole watchOS 2 functionality on the iPhone 4S the following crash will occur:

*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[WCSession updateApplicationContext:error:]: applicationContext cannot be nil.'

Right now I have a work around that checks to make sure the device type is greater than 4S but this might be something you want to check in MMWormHole.

Passing Data from WatchKit extension to App

I am trying to pass some data from watch to app (Cordova app to be exact) but it returns error that my message does not conform NSCoding.

wormhole.passMessageObject("testing", identifier: "sample_queue")

Any one who can direct me on this?

Compiling with non-ARC makes a big issue

Actually I spent lots of time missing this super simple issue out. Please add to the .m file this lines below the imports:

#if !__has_feature(objc_arc)
#error This class requires automatic reference counting
#endif

Error handling using MMWormhole

I incorporated MMWormhole in my app it is working fine with watchOS2 with iOS9. However, it is important to handle error and show it on watch, so is there any mechanism to handle error as it was there in openParent and WCSession in watchos1 and watchos2.

messageObject always nil

I lifted the example code and I do get notified, but the messageObject is always nil in the block handler.
In my watch kit extension, I send:
[self.wormhole passMessageObject:@{@"buttonNumber" : @(1)} identifier:@"button"];

But in my view controller, messageObject is always nil.

Any ideas? I assume it's something simple.

[self.wormhole listenForMessageWithIdentifier:@"button" listener:^(id messageObject) {
// The number is identified with the buttonNumber key in the message object
NSNumber *number = [messageObject valueForKey:@"buttonNumber"];
self.numberLabel.text = [number stringValue];
}];

Use of NSNotificationCenter seems redundant

I can spot no benefit to having the CFNotificationCenter callback post a NSNotificationCenter notification. It should be able to just call didReceiveMessageNotification directly, no?

When integrating with Carthage Umbrella Header warnings are generated

Test Steps:

  1. Create a new test project in Xcode 6.4
  2. Add "github "mutualmobile/MMWormhole" == 1.2.0" to Cartfile
  3. Run carthage update in Terminal
  4. Add the Carthage built MMWormhole iOS framework to the project following the Carthage instructions
  5. Build
  6. Xcdoe will generate the following warnings:
<module-includes>
<module-includes>:1:1: Umbrella header for module 'MMWormhole' does not include header 'MMWormholeCoordinatedFileTransiting.h'
<module-includes>:1:1: Umbrella header for module 'MMWormhole' does not include header 'MMWormholeFileTransiting.h'

MMWormhole does not work when passcode is enabled and iPhone is locked

I'm using MMWormhole in my Watch app. My Watch does not have passcode, iPhone 5s does have it set. Messages are being passed around ok while the phone is unlocked and for some period after the screen goes off.

After few minutes, it just stops and no data come in. I debugged it in and seems that iOS (8.3) cuts off access to the archive files. This data in

NSData *data = [NSData dataWithContentsOfFile:[self filePathForIdentifier:identifier]];

in messageObjectFromFileWithIdentifier: is always nil. As soon as I unlock the phone, then it returns the data properly.

Anyone knows a solution to this? I don't know if this is "working by design" or is some tightened security in 8.3, but it pretty much renders MMWormhole not usable for watch apps.

Crash when unarchiving object

First of all thank you for publishing this framework, it should be very useful for communicating with Apple Watch extensions.

I am trying to receive notifications regarding Core Data updates, as suggested in this thread:
http://stackoverflow.com/questions/27791594/watchkit-core-data-sync-up/29475315#29475315

As soon as MMWormhole sends a message from iOS, the receiving Watch app crashes on the following line:
id messageObject = [NSKeyedUnarchiver unarchiveObjectWithData:data];

It has something to with unarchiving an object (the Core Data ManagedObject I assume)

Full crash report:

*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[NSManagedObject initWithCoder:]: unrecognized selector sent to instance 0x6180000b4820'
*** First throw call stack:
(
    0   CoreFoundation                      0x000000010f346c65 __exceptionPreprocess + 165
    1   libobjc.A.dylib                     0x000000010efdfbb7 objc_exception_throw + 45
    2   CoreFoundation                      0x000000010f34e0ad -[NSObject(NSObject) doesNotRecognizeSelector:] + 205
    3   CoreFoundation                      0x000000010f2a413c ___forwarding___ + 988
    4   CoreFoundation                      0x000000010f2a3cd8 _CF_forwarding_prep_0 + 120
    5   Foundation                          0x000000010eb38584 _decodeObjectBinary + 2872
    6   Foundation                          0x000000010eb39587 -[NSKeyedUnarchiver _decodeArrayOfObjectsForKey:] + 1832
    7   Foundation                          0x000000010eb38b51 -[NSSet(NSSet) initWithCoder:] + 203
    8   Foundation                          0x000000010eb38584 _decodeObjectBinary + 2872
    9   Foundation                          0x000000010eb39587 -[NSKeyedUnarchiver _decodeArrayOfObjectsForKey:] + 1832
    10  Foundation                          0x000000010eb584aa -[NSDictionary(NSDictionary) initWithCoder:] + 203
    11  Foundation                          0x000000010eb38584 _decodeObjectBinary + 2872
    12  Foundation                          0x000000010eb378da _decodeObject + 278
    13  Foundation                          0x000000010ec05a61 -[NSNotification initWithCoder:] + 113
    14  Foundation                          0x000000010eb38584 _decodeObjectBinary + 2872
    15  Foundation                          0x000000010eb378da _decodeObject + 278
    16  Foundation                          0x000000010eb5a971 +[NSKeyedUnarchiver unarchiveObjectWithData:] + 89
    17  My WatchKit Extension               0x000000010eaa4f71 -[MMWormhole messageObjectFromFileWithIdentifier:] + 225
    18  My WatchKit Extension               0x000000010eaa53f2 -[MMWormhole didReceiveMessageNotification:] + 194
    19  CoreFoundation                      0x000000010f31654c __CFNOTIFICATIONCENTER_IS_CALLING_OUT_TO_AN_OBSERVER__ + 12
    20  CoreFoundation                      0x000000010f214a04 _CFXNotificationPost + 2484
    21  Foundation                          0x000000010eb25968 -[NSNotificationCenter postNotificationName:object:userInfo:] + 66
    22  My WatchKit Extension               0x000000010eaa5270 wormholeNotificationCallback + 208
    23  CoreFoundation                      0x000000010f31654c __CFNOTIFICATIONCENTER_IS_CALLING_OUT_TO_AN_OBSERVER__ + 12
    24  CoreFoundation                      0x000000010f2cf86e ____CFXNotificationPostToken_block_invoke + 142
    25  CoreFoundation                      0x000000010f27a41c __CFRUNLOOP_IS_CALLING_OUT_TO_A_BLOCK__ + 12
    26  CoreFoundation                      0x000000010f270165 __CFRunLoopDoBlocks + 341
    27  CoreFoundation                      0x000000010f26ff25 __CFRunLoopRun + 2389
    28  CoreFoundation                      0x000000010f26f366 CFRunLoopRunSpecific + 470
    29  Foundation                          0x000000010eb84f92 -[NSRunLoop(NSRunLoop) runMode:beforeDate:] + 275
    30  Foundation                          0x000000010ec10080 -[NSRunLoop(NSRunLoop) run] + 74
    31  libxpc.dylib                        0x0000000111c21aa9 _xpc_objc_main + 386
    32  libxpc.dylib                        0x0000000111c23e91 xpc_main + 185
    33  Foundation                          0x000000010ecfcee1 service_connection_handler + 0
    34  PlugInKit                           0x00000001196c8a82 -[PKService run] + 521
    35  WatchKit                            0x0000000110ad8c44 main + 126
    36  libdyld.dylib                       0x000000011196b145 start + 1
    37  ???                                 0x0000000000000001 0x0 + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException

listenForMessageWithIdentifier always returns 'nil' in callback messageObject

Trying to use this to communicate from phone to watchKit app and having trouble receiving the messageObject in 'listenForMessageWithIdentifier' callback.
The listener gets fired (confirmed with breakpoints) but the 'messageObject' is always nil.

Phone Code:

self.wormhole = MMWormhole(applicationGroupIdentifier: "my.group.identifier", optionalDirectory: "wormholeDirectory")
self.wormhole?.passMessageObject(["sayHello": true], identifier: "wormholeMessageIdentifier")

WatchKit Extension Code:

self.wormhole = MMWormhole(applicationGroupIdentifier: "my.group.identifier", optionalDirectory: "wormholeDirectory")
self.wormhole?.listenForMessageWithIdentifier("wormholeMessageIdentifier", listener: { (messageObject) -> Void in
        if let object = messageObject as? [String: AnyObject]
        {
            if object["sayHello"] as Bool
            {
                ...code...
            }
        }
    })

Xcode 7 build warnings

Getting the following build warning with Xcode 7 -

/MMWormhole/Source/MMWormholeFileTransiting.m:36:17: Method override for the designated initializer of the superclass '-init' not found

MMWormhole seems not to function anymore

with b5, I cannot seem to get any comms running thru the wormhole, bridged via Swift/in Swift code. I see it open on both ends, but nothing is passing thru. even looking directly after writing return nil:

var wormhole = MMWormhole(applicationGroupIdentifier: "group.mclovin", optionalDirectory: "theRift")
wormhole.passMessageObject(["isSuperbad":true], identifier: "hawaii")
println(wormhole.messageWithIdentifier("hawaii")) <- nil

Can anyone confirm this?

Any chance to work with iOS9/watchOS 2.0?

Hi there.

My current apple watch app relies in wormhole to exchange info between the iphone and the watch. I'm updating the app to the new Swift 2 / watchOS 2 and it would be really cool if I could keep using your library because... it just works! I know Apple now says: "Watch apps that shared data with their iOS apps using a shared group container must be redesigned to handle data differently" but I wonder if this applies to a third party library like yours too.

Thanks

a crash

hi,i find in sometimes the listenerBlock will call a lot of times and then crash,is it i call pass message with same identifier too quickly so that the first is not save succeed?

Add support for NSKeyedArchiver

We plan to add support for NSKeyedArchiver by checking the contents of the passed message. If the contents can be serialized as JSON they will be. If not, they will fall back to NSKeyedArchiver/NSCoding support.

listenForMessageWithIdentifier called twice

Hello,
I am calling the [self.wormhole passMessageObject:@"test" identifier:@"myEvent"]; method from my apple watch. To implement the listener I am using the following code in my iOS app : -
[appDelegate.wormhole listenForMessageWithIdentifier:@"test" listener:^(id messageObject) {
// perform action here
}];
My issue
The "listenForMessageWithIdentifier" is called twice in my iOS app although I have called passMessageObject from my apple watch only once. This scenario is reproduced randomly in my code. Also I have confirmed by the number of times of particular methods called by debugging watch and iOS app on the same time.

Thanks in advance.

"Wrong Architecture" message on iPhone 4/4s, iOS 8.3

I am bringing in the Wormhole library via Cocoapods. Everything works as expected on iPhone 5 and 6, but on 4s simulator it crashes at launch with the error below. Looks like all the architecture settings are correct and in-sync between app and used frameworks.

Library not loaded: @rpath/MMWormhole.framework/MMWormhole Referenced from: /Users/myuser/Library/Developer/CoreSimulator/Devices/F04DCEBB-2E34-49C7-9554-E6048D3349E2/data/Containers/Bundle/Application/BC69F59F-7896-44BE-A7E6-26B46A47E7FD/AppName.app/AppName Reason: no suitable image found. Did find: /Users/myuser/Library/Developer/CoreSimulator/Devices/F04DCEBB-2E34-49C7-9554-E6048D3349E2/data/Containers/Bundle/Application/BC69F59F-7896-44BE-A7E6-26B46A47E7FD/AppName.app/Frameworks/MMWormhole.framework/MMWormhole: mach-o, but wrong architecture

Not getting message in Swift

I'm facing some issues. Kindly answer me to fix the issue. On iPhone app side I'm using this

let wormhole : MMWormhole = MMWormhole(applicationGroupIdentifier: "group.com.xyz", optionalDirectory: "ProjectDataDict")
wormhole.passMessageObject("message recieved or not?", identifier: "ProjectData")

Just this code on iPhone side no. And on swift side I am doing this

wormhole = MMWormhole(applicationGroupIdentifier: "group.com.xyz", optionalDirectory: "ProjectDataDict")
let messageObj = wormhole.messageWithIdentifier("ProjectData")

But it is not giving me any message. Kindly tell me the issue. . .

Problem In function messagePassingDirectoryPath reading Queue

Hi,
I'm testing the library and I have a problem with messagePassingDirectoryPath.
When I generate a Message it's work correctly, but when I'm listening I have this issue:

I use listenForMessageWithIdentifier function to listen messages and when in the library flow come into messagePassingDirectoryPath function line:

NSURL *appGroupContainer = [self.fileManager containerURLForSecurityApplicationGroupIdentifier:self.applicationGroupIdentifier];
always return null value

self.applicationGroupIdentifier variable have a correct value with my group.

If I override NSString *directoryPath = appGroupContainerPath; with a string with my actual path
Something like (@"/Users/gero/Library/Developer/CoreSimulator/Devices/FA4C68DD-4F63-42B3-89A5-6C611A298199/data/Containers/Shared/AppGroup/B049FE4D-EE9F-44E3-AE2A-897C05447471/wormhole/) it's work, and I received messages correctly

Do you know if it's a issue or I need configure something?

Regards,
NeoGeRo

Not working

Hi.
I added source in my project and changed name App-group, but nothing not work.

Completion handler of the method listenForMessageWithIdentifier: not called

I have set up a wormhole form the main app to the Watch Kit App and the other way around. I think that I have set up the app group correctly, because Core Data sharing is working between the targets.
After I send a message from the main app to the Watch app, the method messageWithIdentifier: finds a message, but the listener I have set up is not working. It seems to me, that the completion handler is not called, because there are no logs appearing when I try to log the messageObject.

Not able to pass data from an action extension

Hi,

I'm trying to pass data from an action extension to its parent application through MMWormhole but it doesn't seem to work. Is it possible to use MMWormhole for this or not?

I have added in viewDidLoad()of my main view controller:

wormhole.listenForMessageWithIdentifier("ignore", listener: { (messageObject) -> Void in
    if let message: AnyObject = messageObject {
        print(message)
   }
})

But when I'm doing wormhole.passMessageObject("yo", identifier: "ignore")from my action request handler (used when a user touch the button linked to my app action extension) it's not printing anything.

Passing the message object when touching a button in the application is working so I'm thinking that there is a problem due to having the application in background but I didn't find anything about this issue online.

Thank you for your work!

Multiple notifications

We encountered this issue in our WatchKit app:

ISSUE:
Calling listenForMessageWithIdentifier n times for an identifier will register n callbacks at the DarwinNotifyCenter. When passing a message, the wormhole broadcasts it n times.

SOLUTION:
A possible solution would be to change registerForNotificationsWithIdentifier by adding:

[self unregisterForNotificationsWithIdentifier:identifier];

Like this:

  • (void)registerForNotificationsWithIdentifier:(NSString *)identifier {

    // Only registers once!!!
    [self unregisterForNotificationsWithIdentifier:identifier];

    CFNotificationCenterRef const center = CFNotificationCenterGetDarwinNotifyCenter();
    CFStringRef str = (__bridge CFStringRef)identifier;
    CFNotificationCenterAddObserver(center,
    (__bridge const void *)(self),
    wormholeNotificationCallback,
    str,
    NULL,
    CFNotificationSuspensionBehaviorDeliverImmediately);
    }

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.