Apple’s Worldwide Developer Conference (WWDC) has just wrapped up, and as developers of software for Apple platforms we naturally look forward to learning what’s in store for the next iOS and OS X (recently retitled macOS) releases.
At the very least we begin to learn what may need to be tweaked in our apps so they are compatible with these upcoming fall releases. But beyond that, there’s always the possibility that Apple will add something new to the platform, a new framework or module say, that inspires us to add an exciting feature to Bipsync Notes on iOS or on the Mac.
Last year we were desperate to see much needed fixes to the then nascent WebKit module, which powers the note editor in our iOS app. This year, beyond hoping for general improvements to the key Cocoa frameworks that we rely on like Core Data and UIKit, we had no such wish list.
So considering our relatively low expectations, how did this year’s event deliver?
There were a few particular announcements that interested us as we were able to immediately see how they’re relevant to our apps now, and where we intend to take them in future. Unfortunately many of the features that Apple seemed most excited about, from the new Apple File System to SiriKit (which allows third party apps to integrate with the voice assistant), don’t fall into that category – leaving us with a mild feeling of disappointment.
Nevertheless there’s a few things we’re looking forward to getting our hands on soon, and I’ll briefly run through each of them.
Improvements to Core Data
Core Data is probably the most pervasive of the Cocoa Touch frameworks in our Bipsync Notes iOS app, as pretty much every view is data driven. So any improvement to it always goes down well with us.
This year will see some of the most significant additions to the framework in some time, possibly since iOS 5 when Apple greatly simplified concurrency by adding serialized queuing to the Managed Object Context confinement model.
One of the things I’m most excited about is NSPersistentContainer, a new class which will wrap up the pain of managing a Core Data stack. We have a similar class in our codebase, whose function it is to orchestrate the initial setup of the database and also make available the Managed Object Contexts with which we can query our users’ data.
For a long time Apple’s sample code used the App’s delegate to set up the stack, which was flawed from a design perspective. They recently changed their documentation to recommend it be handled by a custom DataController class, which is akin to what we do, and as of iOS 10 and macOS Sierra they’ll now be offering such a class for free.
NSPersistentContainer also has a neat method called `performBackgroundTask` which allows blocks to be run on an ad-hoc basis without interrupting the main thread. This could potentially bypass the need for us to manage our own background contexts to perform concurrent reads and writes. Nothing pleases a developer more than being able to delete some code, so this is all good news.
Another highlight covered in the WWDC session was Xcode’s new functionality for generating classes of entity models, and managing them as the Managed Object Model changes, keeping the code in sync with the model design.
This effectively replaces the need to use Mogenerator, of which we’ve previously blogged our admiration. As with Mogenerator we’re free to extend the generated classes to add custom functionality, but since Xcode will store the generated class files in Derived Data, they’re not committed to version control, and are essentially invisible. I’m not sure whether that’s a good thing or not – generally I prefer all code to be checked in to the repository, whether it be our own, generated, or owned by a third party. I guess we’ll have to try it out to judge it, but hopefully Mogenerator isn’t going anywhere just yet.
Finally a word on concurrency: Apple has removed the logic which locked the NSPersistentStoreCoordinator instance when a context needed to contact the persistent store, be that to read or write. This effectively created a bottleneck though which only one context could pass at a time, and meant that despite our best efforts we couldn’t completely eradicate UI slowdown on the main thread while our data importer was writing to the database on the background thread.
With NSPersistentStoreCoordinator no longer managing locking, and Apple instead relying on SQLite’s built-in connection pooling (which allows multiple reads at the same time as a single write), our app should feel much smoother.
For example, scrolling through a notes list was an interaction that was noticeably affected when the app was also managing the persistence of incoming data, but in theory this should now no longer be an issue. We had been deliberating switching to two separate Core Data stacks as has been discussed by Florian Kugler, but it now seems fortuitous that we’d held out as it appears we’ve saved ourselves a lot of redundant work.
As the Bipsync Notes iOS app has gotten more complex we’ve spent more time in Instruments, Apple’s debugging toolkit, inspecting what happens when the app runs in order to find ways to make it ever faster and more reliable. The Allocations and Core Data instruments have been particularly helpful in tracking down hard-to-fix bugs in the past.
With Xcode 8 comes two new tools that look very promising: Thread Sanitizer, and a memory debugger.
The Thread Sanitizer tool is able to detect when a thread does something it shouldn’t. This could be some code removing a lock which was opened on another thread, or a race condition caused by multiple threads operating on the same memory address without synchronization. We’ve seen such issues in our app, and they’re a pain to identify. Thanks to a nifty algorithm Thread Sanitizer can identify these issues even if they didn’t actually occur while the app was in use, which means these horrible heisenbugs should be much easier to fix now that we don’t necessarily need to be able to reproduce them.
The memory debugger is an enhancement to Xcode’s existing inline debugger, profiling the allocation tree so it can instruct the developer as to where memory has been allocated, and subsequently leaked. It not only identifies leaks, but can highlight exactly where in the code the problem was caused. We’ve found memory leaks to be less of an issue since we stopped using the Manual Retain-Release model of memory management for the Automatic Reference Counting approach, but they still happen, often when making use of blocks in Objective-C. We’re looking forward to putting this tool through its paces.
The Static Analyzer tool has also been improved so it can now flag up nullability issues, such as methods that return nil when they have indicated the opposite. Addressing these issues is key to allowing an app to support both Objective-C and Swift languages at the same time, as we will likely do in the future.
In iOS 9 Apple introduced App Transport Security to restrict URL requests to only execute over the HTTPS protocol by default, heightening the security and privacy of users.
This is a nice feature but it’s problematic for apps which include some sort of feature that exposes third party web content, such as a browser, or our own note editor. We do not host the HTML that is being loaded and the only way to allow it to display as originally intended was to turn off ATS for all domains aside from our own, which meant that requests to our own API were performed over HTTPS with the remainder being made over HTTP.
Now with the new NSAllowsArbitraryLoadsInWebContent setting in iOS 10, ATS is able to differentiate between the requests that are made from our app to private servers, and those that are made to somewhere on the open web. We can change our app’s configuration so instead of whitelisting everything aside from our own API for HTTP transport, we in fact invert that logic and only approve web content requests for HTTP transport, forcing everything else to use the HTTPS protocol. This will further tighten the security of the app, which is good news for our users and their employers.
Apple spent a lot of time talking about the new SiriKit framework, which we are unlikely to integrate with any time soon. However there was a related announcement which didn’t receive much attention, which was that Apple is now also offering a new Voice Recognition API which can be used for voice to text transforms, for example.
This could be great for a number of features for a note taking app, not least the ability to record audio then later provide a transcription of it as an accompanying document. This could potentially be great for memos but possibly also meeting notes, conference calls, and so on, and as the API works with files as well as streamed audio we could even allow it to work on historical audio recordings.
The audio does need to be sent to an Apple server for analysis which might pose an issue, but it’s certainly something we’ll be investigating in the months to come.
Stickers in Messages.app
Only kidding. We’re not 12!
That just about wraps up what we’re excited about for the forthcoming releases of iOS and macOS. Did you watch the keynote? What stood out for you? Let me know what you thoughts at @craigmarvelley