If you use Network SSIDs in your application you most likely have a breaking change or two in store for you in upgrading to iOS9. Most likely you are using a block of code that looks something like the below to get the current SSID of the device.
The NEHotspotHelper class is part of the Hotspot improvements introduced in the NetworkExtension framework. There is a great WWDC video, “What’s New in Network Extension and VPN” which goes into detail on these new features and the associated breaking changes.
Unfortunately implementing NEHotspotHelper isn’t as easy as adding a conditional, you will need to add the new “com.apple.developer.networking.HotspotHelper” entitlement in your project. You will need to contact Apple to request this entitlement and complete a short questionnaire before this option will appear
Unlike most entitlements, you will need to contact Apple as outlined here to request access to the Network Extension entitlements for your team. I’m still in the approval process so will see how easy it will be to switch to NEHotspotHelper.
Change are if you are using Swift for more then “Hello World” you will need to interact with existing Objective-C libraries such as FMDB, FCModel, MMWormhole, or something similar. Although Apple has come great documentation and there is a WWDC video discussing this I thought it might be helpful to walk through my experiences as someone new to Swift.
As I do most of my mobile development around the native aspects of the Titanium framework, I thought it would be interesting to explore writing native extensions in both Objective-C and Swift. So as part of the Ti.Wormhole project, I provided examples in both languages. Since the MMWormhole project which Ti.Wormhole is based upon is written in Objective-C, a bridging header is required to talk between the Swift extension and the wormhole.
The first step in creating the bridging header is to add a header file to your project. This is just like adding any other header file, just using the [MyProjectName]-Bridging-Header.h naming contention. If you haven’t done this before, in Xcode select File –> New –> File… from the menu then select Header File as shown below.
Then press Next and enter the name of your bridging header. This needs to be done in the [MyProjectName]-Bridging-Header.h, in the following screenshot this is shown as TodaySwift-Bridging-Header to match our extension name. If you have multiple targets like in the WormholeExample project you will want to select the correct Target or Targets to apply. I also found that the bridging header likes to be in the root of your project, so would recommend avoiding placing the file in a nested directory. After verifying your Targets, Naming, and placement, press the Create button to continue.
You will now have a file with contents similar to the below. To allow Swift to access your Objective-C libraries you just need to #import the headers for your libraries as shown below with the MMWormholeClient.h.
Next you will need to update your Target’s Build Settings to reference your Bridging Header. This is done by opening the Building Settings tab in Xcode and scrolling down to the Swift Compiler section. Here you want to update the Install Objective-C Compatibility Header option to Yes and enter the name of your Bridging Header file into the Objective-C bridging Header option as shown below.
You are almost ready to start using your Objective-C libraries from Swift. The very last thing you need to do is import Foundation at the top of the Swift file you are using to reference Objective-C. This is demonstrated in the example project Swift file here and illustrated in the screenshot below.
In the native world, Mutual Mobile solved this with their MMWormhole project. MMWormhole uses the Darwin Notifications and your application’s shared directory to pass messages between your app and your extensions. This seemed exactly what was needed to create events between your Titanium app and extension (or Watch Apps).
After some experimentation and hacking, a Titanium friendly version of MMWormhole called Ti.Wormhole as created. This allows for events to be published/subscribed between native extensions and your Titanium app. This is done through a native Wormhole client that you add to your native extension communicating with a native Titanium module installed within your app.
Ti.Wormhole in Action
The following video shows a quick walk through of the Ti.Wormhole running in the iOS simulator.
Before you get started
Before you get started, this development approach requires you program largely in native ( Objective-C or Swift ). So if you are not comfortable in Xcode, you might want to explore another alternative. Next, you will need a nightly build of Titanium 3.5.x or greater.
How does it work?
The mechanics are of Ti.Wormhole are straightforward. Messages are passed from MMWormhole in your Titanium app using a native module to your native extension. In your native extension another version of MMWormhole receives your messages providing you the information passed from your Titanium app. All Ti.Wormhole really does it make MMWormhole work nicely with Titanium.
Native Extension to Titanium
Native to Titanium
A diagram is great but how does this actually work? Well… to broadcast events from your extension to a Titanium app the first thing you need to do is to create an instance of the MMWormholeClient class. This class is one half of the bridge you need between your Titanium app and extension. The below shows how to create this class in both Objective-C and Swift. The key thing to remember, is the GroupIdentifier and Directory need to match the parameters use by the Titanium module. Otherwise your messages will not be received.
Next your native extension needs to send a notification. This is done using the passMessageObject function of the MMWormholeClient class. The important thing to remember here is that the identifier provided, needs to be the same as the event you are listening to in your Titanium app. In the below example we are broadcasting to an event named wormEvent.
That is all we need to do from our native extension, the rest will be done in our Titanium app.
The first thing we need to do in our Titanium app is to require an instance of the Ti.Wormhole module.
var wormhole = require('ti.wormhole');
Next we use the start method to configure the module to interact with the MMWormholeClient class in our native extension. The key thing to remember here is that the suiteName and directory need to match the parameters used to create the MMWormholeClient class instance in your extension.
suiteName:"Your suite identifier",
directory:"Your message directory"
Finally, you just need to use the addWormhole method to create an event listener. This will listen for a specific event and generate a callback when it is triggered.
console.log("Event in ti app: " + JSON.stringify(e));
Titanium to Native
It is just as easy to go from Titanium to Native. The following diagrams the end to end process that is used in sending messages from Titanium to your native extension.
I know what you are thinking, another diagram great, show me the code. To save time we will skip over the requiring the Ti.Wormhole module and calling Start method. This would be the same as the Native to Titanium example.
The first step is to send a message from Titanium using the Ti.Wormhole module’s post method as shown below. Since you will want to background your app and access notification center, you might want to use setTimeout to give yourself a few seconds.
By calling post, a message is placed into the notification queue to be picked up by your native extension. To receive these notifications you need to add a listener in your native extension as shown in the following Objective-C and Swift examples.