Under The BridgeUnder The Bridge

TestFlight Spreads Its Wings

You catch the latest TestFlight news just now? This looks pretty interesting:

What’s New in TestFlight

TestFlight in iTunes Connect now provides multiple build support, enhanced group capabilities, and improved tester management—making it even easier to test your apps.

Multiple Builds

TestFlight now lets you distribute and test multiple builds at the same time, so testers can choose from a number of builds to test.


TestFlight groups have changed. You can now do more with them, like create groups of TestFlight users, and each group can test a different build. To get you started, we’ve added all of your existing external testers to the group “External Testers,” which you can edit at any time.

Tester Management

Testers can continue testing a build when it goes live on the App Store, minimizing disruptions. iTunes Connect users can also access all active builds, letting them seamlessly compare different builds and you can easily resend invitations to testers who have not yet accepted their invitation.

Learn more about TestFlight.

Well doesn’t that just sort a whole lot of issues we routinely run into amirite? Sure we can play games with app IDs and icon tagging and whatever, not even going to bother linking to our various posts on tips and tricks for that kind of thing, but this looks waaay easier.

Mind you, we haven’t actually distributed an app using Apple’s incarnation of TestFlight yet, next one’ll be the first. When they first acquired it the no iOS 7 thing was a flat out dealbreaker, and by the time that wasn’t well we’d settled into a Crashlytics centred flow nicely so eh whatever dudes.

First time it crossed our mind hmmm maybe we could rethink that was this post last fall

How Not to Crash #1

Interestingly, these crashes did not appear in our usual crash reporting service, HockeyApp, so it actually took us a while to realize that we had a problem. To be aware of all crashes, developers need to check for crash reports through iTunes Connect or Xcode too…

Well, if we have to check them there, why bother checking other places too? Always like to streamline our process, being awesome DevOps dudes and all. But that wasn’t enough to seriously consider going all in, until a few weeks ago Google gobbled as Google gobbles and we were a tad miffed you might recall

Clearly this is great if you’ve already bought into the Firebase platform, but if you haven’t there’s a bit of thinking to do now, especially for those of us in businesses that Google actively competes with so have a smidgen of trepidation about handing over our collective user profiles and activity. Paranoid, yes yes, but hey paranoids have enemies too.

So that was enough to prod us into actively researching alternatives. In our considered opinion Bugsee is the best out there right now by a spectacular margin, oooh network logs would rock! but oh come on dudes we’re an indie place here (OK, actually these days we’re DevOps at Agoda.com because BANGKOK! come join us we need lots of everything especially iOS, but speaking as Trollwerks here) you actually think we can pay? Heh, that’s cute. And yes yes Dear Reader your favourite is very nice too, but nothing else really struck us as worth the effort to switch to.

But this. This here, this actively solves recurring problems! And far as we’re aware — please correct us if we’re wrong — the only actual downside from a dev perspective remaining with TestFlight is that users can opt out of reporting, and then no doubt those that choose to are the exact ones that would get that one weird crash we’d get grumpies 1-starring us with no way to figure out wtf they’re going on about, which would be … suboptimal. But, oh wait, that problem’s sorted now too, so … what’s left as a practical objection to going all in on TestFlight for your iOS platform needs? Why, nothing we can see!

If there’s anything we’ve still overlooked, please comment, but at first glance our verdict is yep, next project, no Google libs, all in Apple. We’ll update here if any flaws arise in that cunning plan!

Rolling Back In

PSA: Did you think, like us, that Rollout thing looked pretty neat, but questionable despite their assurances

Update Native iOS Apps without the App Store. How is this Legit?

…FYI, Rollout’s SDK is installed on over 50 million iOS devices and there’s never been an app rejected because it uses Rollout. I’m just saying that because it’s good to know that thousands of other developers are using Rollout, so you’re not alone.

Um, yeah. About that:

Apple Rejecting Apps That Use Rollout

Just got this message for a few of my apps that are live in the app store (and have been for years).

“Your app, extension, and/or linked framework appears to contain code designed explicitly with the capability to change your app’s behavior or functionality after App Review approval, which is not in compliance with section 3.3.2 of the Apple Developer Program License Agreement and App Store Review Guideline 2.5.2. This code, combined with a remote resource, can facilitate significant changes to your app’s behavior compared to when it was initially reviewed for the App Store. While you may not be using this functionality currently, it has the potential to load private frameworks, private methods, and enable future feature changes.

This includes any code which passes arbitrary parameters to dynamic methods such as dlopen(), dlsym(), respondsToSelector:, performSelector:, method_exchangeImplementations(), and running remote scripts in order to change app behavior or call SPI, based on the contents of the downloaded script…

Well, that’s a start; how about banning React Native next so we can stop having to argue with pointy-haired bosses that JavaScript sucks? We kid, we kid. We like JavaScripters, really. It’s so cute watching them pretend to be grownups! Okay, we’ll actually stop teasing now, let’s see how Rollout is addressing the situation:

While Apple has not modified its guidelines , it appears that these guidelines are now being interpreted in a more narrow way. We are disappointed that Apple has made this change before we have had an opportunity to address any concerns. We have already reached out to Apple to discuss and are committed to adjusting our offering as needed to remain in compliance under the more narrow interpretation of the guidelines…

We understand and respect the fact that Apple must have the ability to control its ecosystem, and we recognize that our appeal may not succeed.

However, Rollout.io will move forward regardless!

First, for the last year we have been readying an entirely NEW product offering which addresses the entire app development process, not only post-production. This new product, which we will be announcing and launching for developer preview in April, will be in full compliance with Apple’s more narrow interpretation of its guidelines…

Well, good luck with that, guys. We’ll check back in April and update with how that’s going!

All About Errors

Here’s one to bookmark for reference: The veritably _definitive_ guide to

Error Handling in Swift

Regardless of your skill, handling errors is a common task for any developer. As developers we have complete control of the code we write and features we include, but despite our best efforts, we don’t control everything. We don’t control the values our users enter or whether our applications have access to the resources they need. In this post we’re going to look at how we can handle these situations by looking at error handling in Swift…

Pretty certain you’ll find something new here no matter what your skill level:

Up to now we didn’t even realize catch could take a where clause, huh. That’s what a couple decades of C++ will do to you, reflexively cringe in triggered terror at the mere thought of “exception”. But we’ll get through it — that bit about propagating back asynchronously looks particularly interesting!


Providing a unified Swift error API

The Nib-lunged Saga

We’ve historically been big fans of Interface Builder for slapping stuff out there in a hurry mostly by ourselves, but these days working on a pretty big app (200+ nib files) that’s expeditiously transitioning to modernity under the tender care of a rapidly expanding team (join now!) the downsides of visual tools for maintainability, code review, and merge conflicts become … substantial. Soooo, we’re considering that as it comes up to refactor in The Great Swiftening, we drop the whole nib/storyboard concept and go code only. If that situation is on your radar as well, take a look at the roundup here from last fall:

Working Without a Nib

My goal is to make all my projects nibless. Nib and xib files have caused me no end of problems. Even files that haven’t been edited in years spontaneously stop working when Xcode is updated and its xib compiler changes. (Most of the problems manifested on previous OS versions, where it was harder to detect them and to test fixes.) And that’s to say nothing of the advantages that doing interfaces with code offers. I’m convinced that with current technology (e.g. Auto Layout, Swift), using Interface Builder is a poor time investment for non-temporary projects…

Particularly like this addenda:

I use xib’s for everything in Keyboard Maestro. And have special Lint code to detect inconsistencies. Coming to the conclusion I’m an idiot.

Heh. For a deep dive into the code only alternative, check out

IB Free: Living Without Interface Builder and Loving It

However, once my projects increased in complexity, I found myself becoming more and more frustrated: when designs evolved, I would often just have to start the layout over by clearing all constraints. I often couldn’t get complex layouts to work in IB and I did not understand UIKit well enough to implement anything that IB didn’t allow out of the box. This frustration was compounded immensely when I began to work on projects with multiple team members and source control: I couldn’t understand what other team members had done by looking at a diff of xibs or Storyboards, let alone untangle a merge conflict…

Nodding along there, are you? Yeah, us too.

In this blog post, I’m going to describe the benefits of being IB-free, and will show you how to build a project and control a view’s layout using Anchorage.

That last library, that’s what tipped us all the way. Check it out:

Anchorage: “A collection of operators and utilities that simplify iOS layout code.”

A lightweight collection of intuitive operators and utilities that simplify iOS layout code. Anchorage is built directly on top of the NSLayoutAnchor API, so fully supports UILayoutGuide. Each expression acts on one or more NSLayoutAnchors, and returns active NSLayoutConstraints.

Seriously, they’re not kidding about the “lightweight”. iOS 9 layout API is already pretty darn good, and Anchorage makes it look downright fluent. Definitely going to give that a shot at our current Swiftification and see how it works out!

Hailing Frequencies Open

OK, now that was unexpected in a point release:

Managing App Store Ratings and Reviews

iOS 10.3 introduces a new way to ask customers to provide App Store ratings and reviews for your app. Using the SKStoreReviewController API, you can ask users to rate or review your app while they’re using it, without sending them to the App Store. You determine the points in the user experience at which it makes sense to call the API and the system takes care of the rest.

When iOS 10.3 ships to customers, you will be able to respond to customer reviews on the App Store in a way that is available for all customers to see. (This feature will also be available on the Mac App Store.)

Well, that sounds promising, doesn’t it now? Although when you actually look at the new API, there’s some interesting restrictions:

requestReview(): Tells StoreKit to ask the user to rate or review your app, if appropriate.

Although you should call this method when it makes sense in the user experience flow of your app, the actual display of a rating/review request view is governed by App Store policy. Because this method may or may not present an alert, it’s not appropriate to call it in response to a button tap or other user action…

When you call this method in your shipping app and a rating/review request view is displayed, the system handles the entire process for you. In addition, you can continue to include a persistent link in the settings or configuration screens of your app that deep-links to your App Store product page. To automatically open a page on which users can write a review in the App Store, append the query parameter action=write-review to your product URL.

If your first reaction is that you want to control the presentation, go ahead and dupe this Radar

Allow user-initiated App Store rating/review request alert

although we’re going to go out on a limb here and assume that the lack of that ability is a quite deliberate decision, kinda hard to imagine them just forgetting about doncha think? so it’s not likely to happen. But we shall see.

Some more details have trickled out as well:

Apple explains the new App Reviews API for developers

Apple is also limiting the amount of times developers can ask customers for reviews. Developers will only be able to bring up the review dialog three times a year. If a customer has rated the app, they will not be prompted again. If a customer has dismissed the review prompt three times, they will not be asked to review the app for another year. Customers will also have a master switch that will turn off the notifications for app reviews from all developers, if they wish to do that. On iOS you can now use 3D Touch to label a review as “Helpful”, a feature that wasn’t available before for iOS users…

Additional Details on the New App Store Review Features

The replies that developers will be able to leave on App Store reviews will be attached to the user review to which they’re replying. It’s not a thread, per se, because users can only leave one review, and developers can only leave one response to each review, but they will be connected visually. Users can then edit their review, and developers can then edit their reply…

The new APIs will be eventually be the only sanctioned way for an iOS app to prompt for an App Store review, but Apple has no timeline for when they’ll start enforcing it. Existing apps won’t have to change their behavior or adopt these APIs right from the start…

So there you go, start planning your New Improved Review Begging UX now!


How & when to ask for app reviews and ratings including iOS 10.3

Notifications Are Better Than Alerts

Fabric, R.I.P.

Catch the news yesterday? That was a mild surprise:

Fabric is Joining Google

Welcoming Fabric to Google

Although only mild, we grant you, because, well…

Indeed. Clearly this is great if you’ve already bought into the Firebase platform, but if you haven’t there’s a bit of thinking to do now, especially for those of us in businesses that Google actively competes with so have a smidgen of trepidation about handing over our collective user profiles and activity. Paranoid, yes yes, but hey paranoids have enemies too.

Not much out there in the way of comprehensive alternatives for your development deployments left though: for cross-platform development this Visual Studio Mobile Center thing that HockeyApp is growing up into might be interesting, but that looks like pretty much it, really.

‘Course, you could always just go all in on Testflight and let other platforms fend for themselves; it’s the easiest by far, that it’s iOS 8 or later should be no longer a problem in 2017 — if that still is a problem for you, our most sincere condolences — plus we gather that frontloading the binary approval process into the beta distribution is supposed to make the final review go noticeably quicker. That would be a quite acceptable tradeoff indeed for having to get your betas approved; does anyone have any firm statements and/or evidence that using TestFlight does actually expedite final review, or is this urban legend?

And as always, if we’ve missed the beta distribution method of your choice here, please educate us!

Padding it Out

So you thinking the rumours swirling about the A10X and the iPad Pro Mini sound … compelling? Yeah, us too. If those turn out anywhere close to reality, looks like 2017’s going to be the year we go all in on iOS, at least to the extent of travelling (which we do a good bit of, now that we’re based out of Bangkok and all). Last year, that was just about practical:

A Computer for Everything: One Year of iPad Pro

… I use my iPad Pro for everything. It’s my writing machine and favorite research tool, but I also rely on it to organize my finances, play games, read books and watch movies, program in Python and Workflow, and manage two successful businesses. While I’ve been advocating for such multi-purpose use of the iPad platform for a while, the iPad Pro elevated the threshold of possibilities, reaching an inflection point that has pushed others to switch to an iPad as their primary computer as well…

“What, how on earth can you work on apps off an iPad?”, you ask? Well, there’s number of options there already if you’re a web developer

14 great programming apps for your iPad 2016

Apparently Pythonista 3 is generally well regarded. Which would be great, if, y’know, we’d written any Python since 2013. Oh, wait. Well, for our use case of Xcode-based building process, we’ll give this a shot:

Dringend: A fully-fledged iOS & Mac development environment on iPhone and iPad

Build & run your apps on the go

Dringend lets you build and run your application wherever you are in the world, be it on a beach or whilst relaxing at a cafe. View errors and warnings just like in Xcode and best of all you can run your project on the iPhone or iPad itself. (Mac to act as build server & Dropbox account required)…

Sounds … well, like pretty much exactly what we want, really. We’ll see how that works out in practice and let you know!

Then, since we keep our private stuff on Bitbucket, looks like this is worth a shot too:

Git2Go: The Git client for iPhone and iPad you always wanted

Git2Go is the first app for iOS which unleashes your full development productivity from everywhere. Clone all your GitHub and Bitbucket repositories with just one tap, manage branches and easily commit changes after you’ve edited code on-the-fly – All from your iPhone and iPad!

Yup, looks like that could work too.

Working Copy: a powerful Git client for iOS that clones, edits, commits, pushes & more…

Or that!

Any of you Dear Readers attempted to develop, or at least make an emergency patch release with, an iOS app with any of these? Or know of any others we should be putting on the trial list?


Matt Gemmell’s thoughts on Designing for iPad Power Users

Linea looks pretty cool: A New Way to Work

Swiftier Swift, Swiftly

Everybody wants their Swift programs to run swiftier, right? In case you haven’t stumbled across it so far, The Canonical List Of Recommended Ways To Do That is found right in the Swift github repo:

Writing High-Performance Swift Code

So you should go read that at the first opportunity and keep an eye on edits too!

Follow that up with this excellently accessible talk:

Real World Swift Performance

Lots of things can make your application slow. In this talk we’re going to explore application performance from the bottom. Looking at the real world performance impact of Swift features (Protocols, Generics, Structs, and Classes) in the context of data parsing, mapping, and persistence, we will identify the key bottlenecks as well as the performance gains that Swift gives us…

Here’s a couple more illuminating posts on instruction level speediness:

Unowned or Weak? Lifetime and Performance

os_unfair_lock is the new synchronization hotness!

Mind you, it’s quite likely that for many of you the most compelling thing that springs to mind on reading the headline there is not swiftier execution, but swiftier compilation, amirite? Here’s some backgrounders and tips on that:

Profiling your Swift compilation times

Guarding Against Long Compiles

Speeding Up Slow Swift Build Times

Regarding Swift build time optimizations

After I read @nickoneill’s excellent post Speeding Up Slow Swift Build Times last week, it’s hard not to look at Swift code in a slightly different light. A single line of what could be considered clean code now raises a new question — should it be refactored to 9 lines to please the compiler? (see the nil coalescing operator example further down) What is more important? Concise code or compiler friendly code? Well, it depends on project size and developer frustration.

Before getting to some examples, let me first mention that going through log files manually is very time consuming. Someone came up with a terminal command to make it easier but I took it a step further and threw together an Xcode plugin

Also check out Swift build time optimizations — Part 2 for followup.

And you’re probably vaguely aware that XCTest does performance these days but haven’t adopted it wholeheartedly yet, right? Check out

measure(): How to optimize our slow code and adjust the baseline

XCTest makes performance testing extraordinarily easy: you give it a closure to run, and it will execute that code 10 times in a row. You’ll then get a report back of how long the call took on average, what the standard deviation was (how much variance there was between runs), and even how fast each of those 10 runs performed if you want the details…

Kinda handy to be able to get hard numbers for your refactoring efforts that easily, indeed.

Any other compilation or execution tips, tricks, and tradeoffs to share, Dear Readers?

Paleo App Dieting

No doubt you’re aware that bigger is not better for downloads on the App Store, especially if you hit the dreaded 100 MB cellular download limit, but were you aware that even if you haven’t there’s a marked disadvantage to download size increasing? Well, here it’s quantified by way of Actual Real Life Experiment:

We bought a successful app, loaded it with extras and watched it fail

… we estimate a linear change in install conversion rate below the 100MB cutoff of -0.45 percent install rate per MB. Above the 100MB cutoff, we estimate a linear change in install rate of -0.32 percent per MB. To our best estimate, the gap between the two lines is covered by a 10 percent instantaneous install rate drop across the cellular download limit.

Although Apple says the cellular download limit is 100MB, we found in practice that a 101MB IPA did not trigger the cellular download block. The actual limit was somewhere between 101MB and 123MB, and it varied depending on the exact build.

Increasing the size of our app from 3MB to 99MB reduced installs by 43 percent, and the increase to 150MB reduced installs by 66 percent in total…

They’ve put together a handy App Readiness Guide with an especially handy App Size Calculator to let you check out your favourite apps.

Sooo, how do we get our size down? If you’re shipping to iOS 9 and later, there’s great options:

App Thinning (iOS, tvOS, watchOS)

  • Slicing is the process of creating and delivering variants of the app bundle for different target devices
  • Bitcode is an intermediate representation of a compiled program. Apps you upload to iTunes Connect that contain bitcode will be compiled and linked on the store…
  • On-demand resources are resources—such as images and sounds—that you can tag with keywords and request in groups, by tag. The store hosts the resources on Apple servers and manages the downloads for you…

Those are generally pretty straightforward to adopt, although you may have occasion to refer to

But if you’re still shipping for iOS 8, none of those help your iOS 8 users at all. Ah well.

First thing is to make sure you’re stripping debugging symbols and dead code with Xcode build settings. Also, make sure that Xcode isn’t bloating your asset catalog behind your back. The setting for that is “Optimization” aka ASSETCATALOG_COMPILER_OPTIMIZATION — and if you haven’t set anything, apparently it defaults to “time” which undoes all your compression and bloats up wildly besides. So set it to “space” instead.

If you need to dig deeper than that, here’s some useful tools for messing with your binary and asset catalog to figure out just what’s going on:

Bloaty McBloatface: a size profiler for binaries

Crunch: “Extract resources from iOS apps. Make iOS icons.”

cartool: “Export images from OS X / iOS .car CoreUI archives.”

AssetCatalogTinkerer: “An app that lets you open .car files and browse/extract their images.”

iOS-Asset-Extractor: “A tool to extract image assets from the iOS SDK.”

And if you need to go still deeper into smallerizing those graphics, well then you’ll have to go to some work. Possibly useful approaches include:

PaintCode is your goto tool for converting vectors into code — and it now supports Swift 3, Android, and JavaScript!

Or you could use SVG files as resourcesMacaw is a new library that looks particularly good for that.

TexturePacker is your goto tool for creating sprite sheets, if that suits your resource usage profile.

ImageAlpha + ImageOptim is an effective strategy for reducing PNG sizes.

JPEGmini is particularly good at making JPEGs smaller.

Or, you could go with the generally well regarded WebP image format, supported by iOS-WebP for instance.

Any more tips? Share and enjoy!

Consistently Immutable

Here’s a good read for when you’re planning a data caching strategy for your Next Great Project:

Managing Consistency of Immutable Models

Immutable models have many advantages, but managing consistency can be difficult. At LinkedIn, we’ve open sourced two Swift libraries to help manage consistency and persistence of immutable models. Unlike Core Data, the API is non-blocking, exception-free, and scales well with large numbers of models and view controllers…

The natural reflex of course is Core Data, and these were their issues:

  • The first problem we ran into was stability…
  • The other issue we ran into was performance…
  • Another issue is there are no eviction strategies…
  • Another point was that migrations are necessary…
  • The final thing for us was scalability…
  • Even if we were to solve all of these problems, we didn’t like the programming model that Core Data provided. One of the things we didn’t like is that all the models were mutable, and they’re not thread-safe, so when you pass it to a different thread, you need to reread from the database…

We could nitpick over how serious these problems actually are if you know what you’re doing, but yeah that last one is kinda a deal. So what would a modern architecture look like, you ask?

What we really wanted to try was to use immutable models for all the data in our application. Immutable models have long been a cornerstone of functional programming languages, and with the introduction of Swift to iOS, I think that they’ve been pushing this idea of immutability. Swift has a bunch of “immutable by default” features, and personally, I’ve been learning a lot about immutability because of Swift. I’m going to list a few of the examples of why immutable models are beneficial:

We’ll assume you know those benefits already, but if not TL;DR they’re easier.

  • We wanted immutable, thread safe models for the reasons which I just went over.
  • We wanted consistency, so a change in one place would automatically be reflected elsewhere in the application.
  • We wanted non-blocking access on all reads and writes. There wouldn’t be any disk access on the main thread.
  • We wanted a simple eviction strategy. Looking at some of our peers, we saw that a lot of apps were using 200, 300, 400 megabytes of disk space, and ideally, for us, we wanted to limit it below 50 megabytes.
  • We want it to scale well. Again, as I said, we have hundreds of models and view controllers, and we wanted easy migrations. Actually, we wanted to write no migration code at all, ever.

To accomplish all these things we wrote RocketData.

RocketData is a caching and consistency solution for immutable models. It’s intended to replace Core Data or at least fulfill that role in an application. It’s written 100% in Swift, and we really like it…

Definitely read it all, but here’s the secret sauce:

The Consistency Manager, as I said, is truly the engine which drives everything. It’s an entirely separate open-source library that RocketData depends on. It’s written completely in Swift, and you can use it independently.

and here’s the executive summary:

Core Data Comparison

There is no tool which will solve every problem. For many use cases, we believe Rocket Data is a better option to Core Data because of the speed and stability guarantees as well as working with immutable instead of mutable models. However, Core Data is useful for other use cases, and it’s important to consider the differences before you make a decision for your app…

Always good to have options … and this looks like a pretty sweet one!


Speaking of options: Core Data or Realm

#35 Structs Alternative: Using Swift Protocols to Enhance Safety of Core Data Access