If you have signed up for Diffusion Cloud then you will probably have seen the Orbs demo which is accessible from your management console. In this post I start rewriting that demo to run natively on an iPhone.
It’s also, by nature, a very visual demo with a surprisingly mesmerising appeal. We may not always want to run the demo with a web browser as the intermediary, so it made sense to write a new version demonstrating our Apple API running on an iOS device. This appealed to me not only from a dogfooding perspective but also as an opportunity to make more than a cursory attempt at learning Swift.
The full source code is available on Github here:
The larger portion of this post is dedicated to my initial impressions of using Swift with our Apple API. We’re keen to experience the same joys and pains that our customers go through when using our SDKs so, while we did spend time ensuring that the API would be as friendly for Swift users as possible, there’s nothing like rolling our sleeves up and getting involved writing a real application. I’ve certainly already spotted a few areas for improvement which we’ll look to address in future releases of the SDK but, on the whole, I can honestly say I found developing in Swift against our Apple API to be functional and clean.
The first task was to create a new iOS application project in Xcode, selecting Swift in the Language field over Objective-C. I could have chosen the ‘Game’ template but I’m not familiar with it and didn’t need the cognitive overload of discovering and learning the baggage that came along with at the same time as doing my best to write elegant Swift code. Therefore I chose to use the simple, familiar and cozy ‘Single View Application’ template.
Diffusion.framework in to a sub-folder in my project’s directory structure allowed Xcode to automatically add it to ‘Linked Frameworks and Libraries’ and configure the
FRAMEWORK_SEARCH_PATHS build setting on import. I also has to add it to ‘Embedded Binaries’ in order to not get a dynamic library error at runtime.
Now that I had a project up and running with the Apple API embedded, development progress was straight forward and followed the path I had anticipated:
- Connect to Diffusion.
- Add topic stream handler.
- Subscribe to topic tree.
- Unpack CSV data received in per-orb updates.
- Model the data in a sensible manner in Swift code.
- Create view and layer infrastructure for rendering orb data and hook it up.
Completion Handlers in Swift
I’m admiring the clean, succinct coding style that Swift naturally encourages. Type inference is one of the most obvious examples of this compact, readable style. There are other examples which don’t leap out so instantly from Apple’s Language Guide but quickly become obvious and lovely to use.
One of these lovely Swift shortcuts goes a long way to validate the heavy use that our Apple API makes of completion handlers for ‘one shot’ type callbacks from asynchronous operations. It’s called trailing closures and allows you to omit the completion handler argument entirely from the method call, simply declaring the closure expression straight after. It’s all covered under Closures in the Language Guide.
This is nicely demonstrated here with the calls to PTDiffusionSession‘s openWithURL and the topics feature‘s subscribeWithTopicSelectorExpression methods. The code’s much cleaner visually when that second argument doesn’t have to be explicitly specified.
One thing I definitely did not anticipate with Swift was the amount of time it would take me to work out how to do anything useful and non-trivial with strings. Specifically I didn’t want to just give up and convert, at cost, to and from NSString until I was sure that I had exhausted my options using the the first class, built in type that was available to me in the language itself.
Code Completion woes
Apple’s Xcode 7.3 Release Notes proudly announce ‘code completion enhancements’. I strongly disagree with Apple’s use of the word ‘enhancements’. It would feel more honest if Apple replaced this with ‘untested, experimental and irreversible changes’ especially in relation to how they impact development in Objective-C.
I was personally so unimpressed with the upgrade to Xcode 7.3 that I’ve elected to remain using the previous incarnation (Xcode 7.2.1) for day to day development on our Apple client library, itself written in pure Objective-C. It really does feel that Apple really don’t do enough testing of their flagship IDE despite their claims as to the number of developers who use it daily and rely on it for their income. I know that AppCode is always ready and waiting in the wings but there’s nothing quite like the feeling of using the official tools.
Failure is an option
Despite my negative experience of attempting to be productive when developing Objective-C code using Xcode 7.3, I found that it was worth using this latest version for Swift development of this demo.
Having a fair bit of Objective-C development experience under my belt I feel entirely comfortable with the concept the object initialisation can fail with
nil. It follows that I was delighted to find that Swift supported the explicit declaration of Failable Initializers. To me this presents the best of both worlds with the compiler able to police this behaviour for callers.
Others disagree with my opinion. That’s programming – everyone comes from a different perspective with their own virtual stakeholders to serve. Unfortunately, despite their announcement in October 2014, failable initializers only really became truly viable for ‘clean code’ use with Swift 2.2 (only available with Xcode 7.3).
The problem I found comes down to use of stored properties defined with the
let keyword. With Swift 2.1 the compiler would insist that they be set before returning
nil despite the fact that the clear intention was to fail! Looking at this line in my demo code, the Swift 2.1 compiler was asserting that neither
orbIndex had been set. Swift 2.2 was happy to let it compile. I think the fact that it’s clearly taken Apple something like one and a half years to ‘fix’ this language feature only goes to emphasise how young Swift really is.
Must… stop… using… semicolons.
After months of purely working in Objective-C, it’s mighty odd not to have to type those semicolons in. Yes the language does allow them but, on the whole and from what I’ve observed, most people are opting to omit them to reduce clutter.
It takes me back to my childhood… oh, those BBC BASIC days…
I spent a couple of days working on writing the demo to this point. The overriding majority of that time was spent exploring Swift. There’s a lot to learn and I found myself doing a lot of ‘tinkering’. I would find myself wondering whether a given portion of syntax was superfluous and could be removed. More often than not it could. Logic abounds.
There’s more I could have explored in this post. For example, the hot topic around singletons and
dispatch_once which does present a few surprises. I solved it in my demo code with a ‘Static’
struct, a pattern seemingly idiomatically adopted by Swift developers.
However, I’m sure I’ve rumbled on for long enough already and you’re keen to go and try some of this stuff out. Hopefully you’ll get as much enjoyment out of pairing Swift with the Diffusion Apple API as I did. Happy tinkering!
The Diffusion® Intelligent Event-Data Platform makes it easy to consume, enrich and deliver event-data in real-time across all network conditions. Push Technology pioneered and is the sole provider of real-time delta data streaming™ technology that powers mission-critical business applications worldwide. Leading brands use Push Technology to bring innovative products to market faster by reducing the software development efforts using the low-code features. The Diffusion® Intelligent Event-Data Platform is available on-premise, in-the-cloud, or in a hybrid configuration. Learn how Push Technology can reduce infrastructure costs, and increase speed, efficiency, and reliability, of your web, mobile, and IoT application.