Peeking Under The Flutter Covers

There are many great articles that demonstrate some of the more prominent features that Flutter offers, such as hot-reloading and cross-platform development.

In this article, however, I’m going to have a look at some of the lesser-discussed aspects of Flutter.

This article is aimed at developers, tech leads and decision makers that are familiar and comfortable with at least one of the two main native development platforms – iOS and Android.

Getting up to Speed

Diving into a new development framework can generally be broken into three separate areas – language, libraries and tooling.


If you know Java (or Swift or Kotlin) moving to Dart is a relatively easy exercise. Most of the flow control statements, data types and data structures will be very familiar.

One area where the Flutter language diverges is that all UI layout is done in code. If you’ve only ever used Interface Builder this may be a little confronting, however, for Android developers who are used to defining layout in XML (and iOS developers who programmatically construct UI, or React/React Native developers) it will be something that will be easy to transition to.

I’ll talk a little more about the specifics later on, but by and large, using the Dart language should not be a major transition hurdle.


This is the hardest part of getting up to speed.

Built-in Library

Developers will need to forget all about native platform functions and features for dealing with the various types. While the language itself isn’t particularly hard to grok, every small action developers have taken on their native platform will now have to be looked up and remembered.

It was surprising how time-consuming this is. For example, developers need to learn which specific Dart properties and functions are needed to:

  • Find the length of a string
  • Determine the index of a string in another string
  • Handle UTF-8 and unicode correctly
  • Add/remove items from a list
  • Manipulate dates (in a safe and sensible way)
  • Deal with exceptions (throwing and catching)
  • Regular expression handling
  • URL manipulation
  • Send/receive data over the network
  • Parse/create JSON
  • Many others…

While not rocket science, I found that I spent a lot of time looking up property/function names to figure out the Dart way of doing things. The built-in Dart library is large and rich – it will definitely take time to re-learn the Dart-specific idioms and features.


Traditional mobile dev has a number of package management tools (Cocoapods, Carthage, Gradle, Maven). Dart introduces another one. The mechanics are quite familiar in that you edit a control file (pubspec.yml), fetch the dependencies, and a file is created that contains the specific versions that were fetched (pubspec.lock).

Nothing too onerous here. However, it takes time to learn what are the typical packages that might be included in a Flutter app. For example, Dagger and Retrofit are ubiquitous in Android projects – what are the equivalents for a Flutter app? Similarly, libraries such as Alamofire and Result are extremely common in iOS apps.


Notionally, Flutter lets you work in either Xcode or Android Studio. However, with Flutter coming from Google, there is obviously a far tighter integration into Android Studio. For example, Android Studio has support for code completion, breakpoints, image swatches, Flutter inspector, template projects, etc.

Personally, I found that developing in Android Studio deploying to the iOS Simulator and Android Emulator was an extremely efficient workflow.

If you’re familiar with Android Studio, this will be a very easy transition. Xcode users will naturally want to continue using Xcode – which I’d say is possible but not advisable, so there’ll be some cross-skilling required for iOS devs to learn Android Studio.

Articles and Self Learning

To be honest, I think the documentation for Flutter is pretty good. They’ve made a conscious effort to provide documents that are guide-based for gettings started, and reference-based for when you want to know a bit more about the specific parameters.

There are quite a few example projects that Flutter provides that demo a range of techniques. However, there is definitely a shortage of articles and example projects that discuss techniques for achieving specific goals or exploring various architectural approaches for building an app.

To be sure, there are some good articles out there, but (as expected) nowhere near the volume for native Android and iOS development. I also found that many articles or github repos are essentially just extensions of the sample projects that Flutter provides in its documentation. For example, I found it very difficult to find decent examples on animation (other than the ones that Flutter provides).


Flutter is in an somewhat awkward situation at the moment as the officially supported language is Dart 1. However, it is in the process of transitioning to use Dart 2 (it may have already done so) and provides some instructions on how to use the Dart 2 beta.


I must admit I had trouble finding a concise description of the specific changes between Dart 1 and 2 (most references just point to a 10,000 line Tex file). From what I can glean though, the major change (which I welcome with open arms) is that types are now mandatory. Dart 1 is a dynamically typed language that supports type annotations. It also offers an additional mode called strong mode which enforces type safety. In Dart 2, types are now mandatory but the compiler allows them to be inferred. If you were already using strong mode in Dart 1, moving to Dart 2 will be much easier.

Sadly, though, Dart has poor treatment for nullability and optionals – at least, compared to Kotlin and Swift (and even Java/Objective-C with their nullability annotations). There are some operators that give a little bit of syntactic sugar when dealing with objects that could be null, however, the compiler won’t enforce nullability checks. There have been a number of proposals, discussions and prototype implementations dating as far back as 2011, however, as best I can tell, it won’t be introduced until after 2.0 is formally launched. This makes me sad.

As a language, Dart is very similar to Java. Many types and their behaviours look exactly the same as their Java counterparts. For example, Dart uses the same distinction between Exception and Error.

While both languages support generics (eg. List<String>), one key difference is that Dart doesn’t implement type erasure.

One thing that is missing from the Flutter implementation of Dart is dart.mirrors, which means code that relies on reflection/mirrors is not possible.

In terms of support for asynchronous activity, the language itself has first-class support for async and await statements which is really nice. It doesn’t use threads, but rather uses isolates which are similar to Erlang actors. An isolate is like a parallel worker, but doesn’t share memory or variables. You can pass data between isolates using messages and “ports”. Another nice touch is first class support for Futures and Streams.

My personal opinion is that Dart is a big step forward from Java, but a backward step from Kotlin and Swift (eg. absence of optionals and associated values in enums). All in all, though, I found it to be a relatively modern, expressive language. I’m sure there are language purists that may contradict me, but as a developer who just needs to leverage the platform to get work done, it is pleasant enough to develop with.

Virtual Machine

The Dart Virtual Machine (VM) is what is used to execute Dart code. The Dart VM is a bit tricky to describe because there are a couple of modes in which it operates:

  • Just in time (JIT) – This is the mode that is used at development time and is what underpins the hot-reloading functionality. In this mode, the Dart VM both compiles and executes Dart source code (in addition to the provision of the runtime libraries). Obviously, this is a bit slower than a traditionally compiled app, but offers a more dynamic execution.
  • Ahead of time (AOT) – Used when packaging your application for release. In this mode, the Dart source gets compiled to native machine code for the hosting platform. In this case, the VM is really only responsible for providing a set of runtime libraries… execution of the machine code is the responsibility of the hosting operating system.
  • Dart byte code (DBC) – This is where your Dart source gets compiled to an intermediate byte code (DBC) that then gets interpreted by the Dart VM. This mode is more analagous to the traditional Java/Dalvik interpreter where the VM interprets a stream of byte codes. I don’t believe this is used in Flutter.

Network Layer


At its most basic, the code to perform a GET request from a remote server looks like:

import 'dart:io';
import 'dart:convert';

var http = new HttpClient();
var uri = new Uri.https('', '/users', { });
var request = await http.getUrl(uri);
var response = await request.close();

// now let's naively convert the raw bytes from List<int> to a String.
var responseString = await response.transform(utf8.decoder).join();

This is a good start, but getting back a String is not particularly consumable by our app just yet.

Converting JSON

Building on the above code snippet, Dart offers some more built-in converters (import dart:convert) to easily transform the String to a List<dynamic> or Map<String, dynamic>.

List<dynamic> listOfUsers = JSON.decode(responseString);

Unmarshalling into Strongly Typed Objects

Although the previous two steps were easily achieved, unfortunately, Flutter has extremely poor support for converting the output of JSON.decode() into strongly typed objects.

Dart does support runtime reflection using Mirrors, however that feature is explicitly disabled in Flutter.

This leaves us with two choices:

  1. Manually write code that maps json to/from our objects ourselves. This is error prone, but relatively straightforward.
  2. Use tooling to generate code that will do it automatically. There are a couple of options here: dson, json_serializable, or jaguar_serializer. While having to generate code is a pain, Dart/Flutter provide some tooling to make things a bit easier.

All in all, converting JSON to/from strongly typed objects is a big step backwards to what most mobile developers are used to with tooling like Android’s GSON/Moshi/Retrofit and iOS’s Encodable/Decodable.

Android vs iOS

One of the great benefits of using Flutter is that you can actually write code once and have it run on multiple platforms. However, it comes at the expense of honouring the native platform interface conventions.

With Flutter coming from Google, it should be no surprise that the design language and widget implementation is heavily slanted towards Material Design. By default, a new project defaults to using MaterialApp which is a bit confronting for iOS users.

Both Apple and Google have spent many years defining both a design language and implementation for how components, screens and transitions are used within an application. Flutter steps away from these patterns in two key ways:

Ground-up Implementation

Because Flutter’s implementation controls the entire rendering pipeline, everything you see on your screen is drawn by Flutter (including animations). As hard as Flutter tries, they cannot guarantee that the widgets and behaviours are the same as the native counterparts. When the operating system changes the way native components are rendered, Flutter apps do not naturally change in the same way native apps do.

If your app is a totally custom design that does not conform to Google’s Material Design or Apple’s HIG, this will not be a problem. However, if your application adopts native platform conventions, this will be a major sticking point.

Platform-specific Widgets

Flutter offers many standard widgets that are platform agnostic. They also offer a set of Android- and iOS-specific widgets.

This sounds really appealing, however, I have two concerns about this approach:

Parity between iOS and Android

At the time of writing, there are only 13 iOS-specific widgets (there are three times as many Android-specific widgets). Given that Google is driving Flutter, I totally understand that it is likely to be Android-first, however as someone responsible for shipping apps with high fidelity across both platforms it remains a concern that iOS doesn’t appear to receive the same level of attention as Android.

A perfect example of this is that the Cupertino widgets do not contain any support for themes, whereas the Material Design widgets contain full support.


In order to use iOS or Android specific widgets, they must be constructed explicitly. ie. you don’t just ask Flutter for a “button” and Flutter decides whether you get a RaisedButton or a CupertinoButton. Instead, you explicitly need to instantiate instances of the platform-specific widgets. Another example is AlertDialog vs CupertinoAlertDialog.

The major consequence of this is that, if you intend to use widgets that conform to the platform’s natural design language, you will need to build two User Interfaces for your app. In theory, you can build a single screen and have your app choose which widget is going to build, however your code will either end up being littered with if conditions or you’ll need to move to some sort of factory pattern that abstracts some of that away.

In addition to having to duplicate your user interface, it is also important to note that neither RaisedButton or a CupertinoButton share any common type ancestry other than StatelessWidget, so there’s no notion of just passing in the button to a function that can do common behaviour.

User Interface

Image handling

As expected, Flutter has support for supplying images based on different pixel densities. They do this using what they’ve dubbed “variants”, which is essentially a fancy name for the existing Android pattern of having sub-directories that contain images with the same name as in the root folder. For example, the following file hierarchy shows how Flutter deals with providing an image for various pixel densities:


The above example represents a single image asset called share.png that has different files for pixel density ratios of 2.0(xhdpi) and 3.0(xxhdpi). This file can be referenced from code by using code like the following:

// return image based on pixel density of current device
var image = Image.asset("assets/share.png");

Note that they’ve moved towards using an explicit ratio. In the case where there is no exact match, Flutter will choose the ratio that is the closest.

Adding images involves explicitly adding them to pubspec.yml and making sure the images are located in the appropriate directory and named correctly. This is quite similar to Android, but a bit of a step backward from using Xcode xcassets.

At the moment, Android Studio doesn’t show images in the gutter (like they do for an Icon), which is a shame.

Also, you run the risk of having typo’s in your image name (unlike Xcode’s #imageliteral). However, I expect that the IDE will eventually get around to supporting these nice features.

I’ve saved the worst for last, though… unfortunately, there is no support for SVGs. There are a couple of open source attempts, but not having first class support for at least one of the vector image formats is a sad story.

Layout management

Flutter’s layout system using an (almost) declarative custom constraint-based framework that is somewhat similar to iOS’s Autolayout and Android’s ConstraintLayout.

An example (taken from the Flutter documentation) of the code to render a small section of a screen might look like:

Widget titleSection = new Container(
  padding: const EdgeInsets.all(32.0),
  child: new Row(
    children: [
      new Expanded(
        child: new Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            new Container(
              padding: const EdgeInsets.only(bottom: 8.0),
              child: new Text(
                'Oeschinen Lake Campground',
                style: new TextStyle(fontWeight: FontWeight.bold),
            new Text(
              'Kandersteg, Switzerland',
              style: new TextStyle(color: Colors.grey[500]),
      new Icon(, color:[500]),
      new Text('41'),

You’ll notice that the layout objects (Row, Column, Expanded, Container, etc) and rules are interspersed within the components themselves (Text and Icon). This is because Flutter’s layout system is built on top of the Widget concept. Layout components are just another part of the widget tree.

Flutter comes with a bunch of bunch of built in layout widgets that let you control things like:

  • Padding
  • Alignment
  • Size
  • Aspect ratio
  • Transformations
  • Flowing
  • Grids
  • Tables
  • Offscreen buffering

One thing that I haven’t been able to find is a way that I can create relative constraints between two widgets. For example, imagine I had two Text widgets and I wanted the first one to be, say, 50% of the width of the second one. If the widgets were peers in the same node of the widget tree, I can see how I might be able to construct my own custom container that defines this layout relationship, however, if the widgets were in scattered in different locations within the widget hierarchy, I feel like it would be much harder. I guess I’d probably start with MultiChildRenderObjectWidget, but it certainly doesn’t look easy.


Flutter has support for several types of animations out-of-the box. It broadly breaks animations down into two general categories: tweening and physics-based.


Tweening is essentially animation between two values. For example, between a height of 50 and 100, a location of (5, 5) to (10, 10), green to red, etc.

Like most animation libraries there are quite a few ways to achieve the same objective. Basically, though, animating in Flutter means externally managing the timing (using something like an AnimationController) and periodically calling setState() in order to force a rebuild.

At first glance, this personally feels a little awkward in that the sequencing of the animation is defined in a different place to the actual application.

Two good articles on Medium give some concrete examples on how to apply some custom animations to your widgets: part 1 part 2

Fortunately, Flutter provides some native transitions that hide some of the boilerplate code, such as SizeTransition, RotationTransition, FadeTransition, and so on.

Even with all that though, I feel like there’s still a little bit of state management (or superclassing) required to perform animations. I’m yet to find a simple, boilerplate-free Flutter version of something like:

UIView.animate(withDuration: 1.0, delay: 0.5, options: .curveEaseOut) {
  // animate a property

Physics Based Simulations

There are a number of simulations that can be used to generate animations with springing, friction and gravity. I must admit, though, I haven’t spent much time investigation these in detail – however, I do know that these simulations are used to provide the iOS-specific scrolling feel.

Writing Custom Components

Flutter heavily promotes component creation by composition. To this end, it is very easy to create new widgets, override the build() function, and away you go.

You can also create “paintable” components that allow you to totally customize the drawing using a canvas that is passed. A very simple example of this that simply paints a red rectangle looks something like:

class RedRectangle extends CustomPainter {
  void paint(Canvas canvas, Size size) {
    final rect = & size;

    final paint = new Paint()
      ..color =[400] = PaintingStyle.fill;

    canvas.drawRect(rect, paint);

  bool shouldRepaint(RedRectangle oldDelegate) => false;

Interestingly, instances of this type cannot be embedded directly in the render hierarchy as they do not subclass Widget. You need to use a CustomPaint widget to wrap them:

Widget build(BuildContext context) {
  return new Scaffold(
    appBar: new AppBar(
      title: const Text("Demo App"),
    body: new Container(
      child: new CustomPaint(
        painter: RedRectangle(),
        size: new Size(200.0, 100.0),

Initially, I thought this was a bit cumbersome, but after a bit more digging I found that you can also add additional children to the CustomPaintwidget. Being able to provide your own painter to the widget tree opens up a huge range of possibilities.


As mentioned earlier in this article, Flutter “supports” the notion of themes – as long as you only use Material widgets. If you use iOS widgets, or write custom components, you have to do theming yourself.

A Theme is, like most UI-related elements, just a widget. By default, the MaterialApp wraps the app within a Theme which will be used by the Material widgets from that point on. At any point, you can have a nested theme from that point forward by wrapping components within your own (perhaps modified) theme.

An example of how you can override the colour of specific widgets is shown below:

body: new Center(
  child: new Container(
    color: Theme.of(context).accentColor,
    child: new Text(
      'Text with a background color',
      style: Theme.of(context).textTheme.title,

Even though the Theme classes are part of flutter/material.dart, in theory, I’m pretty sure it would be possible to extend so that you could still wrap your non-material widgets in a Theme widget. However, as I mentioned before, applying the various theme settings would need to be done on a widget-by-widget basis.

I’m quite disappointed in the decision to only provide theming to Material widgets. Make no mistake, theming across multiple platforms is difficult, however, it would have been nice to at least have the theming infrastructure implemented in a common way even if they only provided a Material implementation.

Tablet support

Unfortunately, I don’t believe there is strong support for iPads and tablets. Doing a search of the flutter codebase, I found less than a handful of lines of code that specifically mention iPad or tablet.

Adaptive Layout

One part of offering tablet/iPad support is adaptive layout and one strength of Flutter is its support for flexible layout. I have a lot of confidence that an individual screen can be coded that expands to fill the available space.

Tablet-Specific Layout

However, these types of devices have different navigational patterns and layouts should be changed in order to make the user’s experience as seamless as possible.

Android offers this capability by using custom layout folders based on qualifiers such as width/height/etc (eg. res/layout-w600dp) which will automatically take into account system decorations and whether the user is in multi-window mode. Similarly, iOS has strong support for this using Size Classes, which native components such as UISplitViewController will automatically recognise.

Writing widgets that are adaptive based on screen size in Flutter is definitely possible but as far as I can tell, there’s no built-in widgets that offer this functionality immediately.

Dependency Management

Dependency management in Flutter is managed using the Pub Package Repository. You can add dependencies by adding them to the pubspec.yaml file in the root of your Flutter project. This file, among other things, controls the list of dependencies that will be installed when you run flutter packages get.

An example of the dependencies section for a very basic app might look like:

    sdk: flutter
  collection: 1.14.6
  device_info: 0.2.0
  intl: 0.15.5
  connectivity: 0.3.0
  string_scanner: 1.0.2
  url_launcher: 3.0.0
  cupertino_icons: 0.1.2
  video_player: 0.4.1

    sdk: flutter
    sdk: flutter

The dependencies section describes the specific packages (and the version number) that will your Flutter app is dependent on at runtime. Like most packaging systems, you can specify a range of version number constraints depending on how strictly you want to control the version number of your dependencies.

You can also define dev_dependencies which are for dependencies that are only needed during tests (or perhaps for build-time processes / code generation).

Once packages have been fetched from the remote location, they are generally stored in $HOME/.pub-cache/hosted/

In terms of what files should be committed, the Dart folk have a pretty good page that describes what the various pubspec files are and which should be checked in.

If your development practice is to commit dependency graph artifacts into your app’s repo, it is a bit tricky to support. I haven’t found a specific technique that works yet, but as best I can tell, you’ll have to fiddle with using a path directive in your pubspec.yaml file and manually move files from $HOME/.pub-cache folder.

Bridging to Native

Calling Native Code

You can call back to native code quite easily using a platform channel. Essentially, this is just an RPC-style call where you can invoke a “remote” method passing some optional parameters.

At its simplest, this looks something like:

const nativeChannel = const MethodChannel("");

try {
  final int result = await nativeChannel.invokeMethod("someNativeFunction");
} on PlatformException catch (e) {

and then on the native side, you’d have code that looks like one of the following:


@objc class AppDelegate: FlutterAppDelegate {

  override func application(
    _ application: UIApplication,
    didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
    // ...

    let channel = FlutterMethodChannel(
      name: "",
      binaryMessenger: controller)

    channel.setMethodCallHandler { (call, result) in

    // ...


class MainActivity() : FlutterActivity() {
  override fun onCreate(savedInstanceState: Bundle?) {
    // ... 

    val channel = MethodChannel(flutterView, "")
    channel.setMethodCallHandler { call, result ->
      result.success(123);  // return 123

You can use a similar technique to invoke methods from your native code back into Flutter code. Asynchronicity is supported in both directions.

There’s very little information that I can find on the relative performance of calls through these channels. Without writing exhaustive performance tests, my impression is that the performance overhead is imperceptible for the occasional call, however, I wouldn’t be wanting to make thousands of calls in a tight loop.

It is worth noting too, that you can create a Flutter plugin that lets you write a Flutter interface that bridges across into native code.

Launching Native Transitions

You can launch native transitions (eg. a Kotlin Activity or Swift UIViewController) by using a platform channel (per above) and manually starting an activity (using an Intent) or pushing to new view controller.

While technically functional, I find this to be a really awkward handoff. Essentially, Flutter is just deep-linking into your native app. If you just need to display a single screen, this will work fine however if you have a mixture of Flutter/native, I can see this creating all sorts of navigational/experience challenges.

Embedding Native Widgets

As far as I can gather, there is no capability to embed a native component (ie. a subclass of UIView, Fragment or View) within a Flutter widget. On one hand, I can see how this would be extremely difficult given that most native components expect to be running within the context of a native run loop. On the other, it means that the extensive open source libraries of native iOS/Android UI components that have been written (and battle-tested) over the past few years are not available for use within a Flutter app.

I can see there is a proliferation of open source libraries being released every day that target Flutter, however it will be quite some time until these components are as rich and well-tested as the current plethora of iOS/Android open source components.

One thing that I have noticed is that many open source Flutter widgets only target a single platform, depending on the author’s familiarity with one or the other. This is totally understandable as many devs are more comfortable/knowledgable in a specific platform, however, it is a question that consumers of Flutter open source libraries will constantly need to be asking.


At the moment, there are a number of coarse grained limitations that I’ve discovered along the way. I’m sure that some of these will be solved at some stage, but at the moment, a couple of the bigger ones that I’ve found are:

  • No flutter code can run in the background. This means there’s no Alarm Manager, Geofencing, or UIBackgroundMode. Now, you can always add this code to your respective native codebase, but for now, there’s no Flutter equivalent.
  • 3D OpenGL is not supported.
  • You’re on your own with ARKit and ARCore
  • Native integration into platform services (eg. HealthKit, Google Fit, Apple Pay, Android Pay, et al) are either not implemented or are unlikely to ever be
  • Maps are not supported
  • As mentioned earlier, vector graphics are not supported.

Secure Storage

Out of the box, Flutter doesn’t provide any libraries that can access iOS’s Keychain or Android’s Keystore. There is one particular 3rd-party plugin that does provide access, but the API is basically a very simple key/value store.


One of the great things about Flutter is that having a single source for the majority of your code means that you only need to write your test cases once. I’ve lost count of the number of times I’ve discovered two slightly different sets of tests for the same business logic in the comparable iOS and Android apps.

Flutter lends itself to super fast unit testing because you should only need the Dart VM to run the majority of your business logic and domain model tests.

If you want to perform UI automation testing, Flutter has a Selenium-like driver that you can use to write scripts that look something like:

test("tap on the button, verify result", () async {
  final SerializableFinder label = find.byValueKey("My label");
  expect(label, isNotNull);

  final SerializableFinder button = find.text("Press Me");
  await driver.waitFor(button);
  await driver.tap(button);

  String value;
  while (value == null || value.isEmpty) {
    value = await driver.getText(label);
  expect(value, isNotEmpty);

Tests can easily be executed from the command line (and thus from a CI environment) by using the following command:

flutter test test/my_tests.dart

When running the tests from within Android Studio, the results are presented using the standard test runner UI which is quite nice.


Flutter has some initial support for accessibility, however the documentation is pretty thin.

Following on from the initial implementation, there are a few outstanding tasks before it could be used in anger.

At the moment, some widgets (eg. Icon) have built-in support for a property called semanticLabel which can be used to provide TalkBack and VoiceOver text. For thos widgets that don’t support a built-in property, you can always wrap it in a Semantics widget. For example, below shows how to wrap a CircleAvatar inside a Semantics widget:

new Semantics(
  label: 'View John's Profile',
  child: new CircleAvatar(
    child: new Text('John'),

While it is great that you can wrap any widget to provide some accessibility assistance, having to add that extra layer for every widget is a discipline that I don’t think will extend to most apps.


Internationalisation(I18N) and localisation(L10N) means many things to many people.

In terms of providing localised content for your app, Flutter has lots to offer as most of its I18N and L10N is provided by the Dart intl package.

For Android, the supported list of built-in locales is relatively modest but I expect that to grow over time.
Sadly, iOS again takes a back seat to the Material Design widgets. Most of the Material Design widgets have some level of built-in localisation, however, I cannot see any localisation logic for the equivalent Cupertino widgets. This makes me sad.

Initially, I thought that the Dart intl package provides pretty solid support for ICU date handling… however, upon researching a bit more, it seems that they do not support timezones. Note that this issue has been around since 2012… wut?! Not only that, but the documentation for DateTime.parse() says:

If a time zone offset other than UTC is specified, the time is converted to the equivalent UTC time.

In today’s world, where apps are used 24×7 all over the world, having no timezone support is bad enough, but to knowingly return incorrect data is simply horrible.

Editors note: I would love to be wrong about this. Please let me know if this is the case.

Packaging and CI/CD

The build process for producing a deployable artefact is slightly different for each platform.


Simply run the following command:

flutter build apk

Under the covers, this just runs gradlew assembleRelease. For a super simple app, this produces an APK that is about 8MB, of which about 2.5MB is in the icudtl.dat localisation file and it looks like the flutter engine takes up about 3.5MB.


The iOS build instructions are a bit unusual. They suggest that you need to first run flutter build ios and then go into Xcode and manually create an Archive. This is great for “Hello World” apps, but is not a workable flow when you’re using a CI server to produce automated builds. Until this gets resolved it looks like the iOS build process consists of running flutter build ios, followed by a subsequent call to xcodebuild.

Interestingly, I can see that flutter build ios is actually running xcodebuild under the covers and it does create what looks like a sensible package in the ./build/ios folder. I’m not sure why they don’t go the extra step and create the ipa file.

The world’s simplest Hello World app creates an un-thinned IPA that is about 60MB. About 30MB of that is the standard Swift library, 20MB is in Flutter.framework, and the remaining 10MB is in App.framework which looks like it contains the compiled Dart code.

Interestingly, the contents of the framework leaks a heap of internal information about the build machine. For example, if I run strings App.framework/App, I see stuff like:


The contents of Flutter.framework/Flutter framework is a bit more benign and appears to contain the flutter engine.

Aside: It bothers me more that it should that one of the flutter build commands uses the artifact extension apk and the other uses the platform name ios. Consistency matters. But I digress…

Multiple Flavors

In theory, Flutter supports different flavors by passing --flavor xxx to the flutter build command, however it doesn’t look like it works properly for iOS (works fine on Android – it just runs gradlew assembleXxxRelease).

For iOS, the recommended way to use a scheme is to pass the scheme name in the --flavor parameter (not sure why there isn’t a --scheme parameter). The problem is that it doesn’t use the configuration that is defined in the scheme, but instead looks for a configuration with the same name as the scheme with a -Release suffix. So, if you run flutter build ios --flavor xxx then you must also have a configuration called xxx-Release.

I’m sure this situation will improve eventually, but from what I can tell, there aren’t any concrete plans to address this. If you use schemes/configurations to manage your Xcode build config (which many apps do), this leaves things in a state of uncertainty.

Push Notifications

Generally speaking, there are two types of notifications: remote and local.

Native remote notifications are caught by the wrapping native application and will need to be passed into the Flutter components using a channel as described above. Alternatively, there is a Firebase plugin provided by Flutter that does a lot of the heavy lifting for you.

There is no native support for local notifications within the Flutter SDK, however, there are several open source plugins.


The Flutter docs are pretty good. Not only do they provide loads of getting started guides and tutorials, they also provide a jumping-off point to the reference documentation for the SDK itself – which, depending on where you look, is also well documented. There are a few examples, though, where the details are pretty slim. All in all, though, I found the documentation to be good.

What is missing, though, are the plethora of blog posts that are available for iOS/Android detailing specific problems that have been encountered and solved. To be sure, there are some good blogs however, given the relative age of the Flutter community, it will take time for these types of articles to appear.

When I’m searching for examples of how to use a particular component, I often just search for projects where others have (hopefully) done something similar. What I found when researching many of the Flutter widgets, though, was that the vast majority of github projects were just clones of the example projects offered by the Flutter team.

The last thing that just isn’t there at the moment are articles describing alternate architectural patterns and how/where they are (or are not) appropriate. For example, there are many iOS posts contrasting MVC, MVVM, Viper, et al. I’ve seen very few of these so far.

I’m sure this will improve over time, however, at the moment there is a definite need for additional blog posts.

There is also a gitter community and a google group that offers some level of support too.


One of the things I’m very conscious of is how apps built with Flutter will be supported in the future. For example:

  • Will Google even support Flutter in a years time?
  • Flutter is evolving very quickly (which is great), however, what is their backward compatibility story? Will an app written today compile in a year’s time? Swift already has a similar problem at the moment, and it isn’t evolving as quickly as Flutter.
  • If I have someone from my team build an app using Flutter, and then someone else has to pick up new features afterward, how is that handoff going to work? How hard will it be for me to cross-train developers?
  • At the moment, iOS developers have a lot of experience in the native UX patterns of an iOS app, just like Android developers do for their platform. If I develop an app using Flutter, are my developers expected to have deep knowledge of the UX patterns for both iOS and Android – as well as knowledge of Flutter. How hard will it be for me to find developers that satisfy these skills, or are motivated to learn them?
  • What is the current skills market like? At the moment, both iOS and Android are beginning to become commodity skills and developers generally have many apps under their belts that contribute to their knowledge pool. How hard is it going to be to find similar developers for Flutter?
  • I work for a digital consultancy. Choosing Flutter for a client app over the native platforms is an important technical decision that could have long-term impacts on my client’s technical stack.

Code reuse

If I think about how an app would be built for two platforms, there are five main components:

  1. Object model, business logic, network unmarshalling, error handling, validation rules, et al. This is the “functional core” that Gary Bernhardt talks about in his Boundaries talk.
  2. Pieces of screens that are common across iOS and Android. For example, imagine you have a screen where the user can update their profile details. The contents of the screen itself (not the chrome outside or the transitioning to/from the screen) are very often exactly the same.
  3. iOS-specific transitions, animations, and patterns
  4. Android-specific transitions, animations, and patterns
  5. Unit tests

Out of these five items, Flutter has an excellent code reuse story for three of them (1, 2, and 5). The exact percentage that these three items represent within your app will vary, but it is almost certainly non-trivial. Having to only build those components once is definitely a time saver – leaving only the platform-specific components to be individually developed.

Note that if your app doesn’t conform to native platform conventions (eg. it is a game or a highly branded UI), then you could argue that even items 3 and 4 could benefit from code reuse.


Ten Point Summary

Things I Like

  • This isn’t just something that has been smashed together. It is an engineered solution.
  • I love the react-style declaration that is used for widget definition
  • Hot loading is amazing!
  • Being able to reuse object models, unmarshalling, network handling, and all of the tests that go with it is excellent.
  • Dart 2 is a strongly typed language making refactoring much easier

Things I Don’t Like

  • Cross platform SDKs mean a dip in native platform convention fidelity. UI components that are built from the ground up are just not the same as native components.
  • Poor iOS support. There are so many things where support for iOS is just tacked on as an after-thought.
  • Supportability is a big question mark that will rule out a bunch of scenarios
  • Network unmarshalling is a big step backwards to what we’ve been used to with Codable and Retrofit.
  • Lack of timezone support. While seemingly a single micro-issue, this really bothers me.

Would I Use It?

As always, “it depends”.

Apps I Wouldn’t Use It For (yet)

  • A flagship app that is going to be extended and maintained for years to come. I’m still very wary of the support burden.
  • Apps where following native UI/UX conventions is important.
  • Apps where my client is conservative with their tech stack approach.
  • Apps that have high native interaction (HealthKit, ARKit/ARCore, etc). I would, however, consider in-app purchasing and just bridging between the native code and Flutter.
  • An app that only needs to be built on one platform, although, having said that some of the productivity gains (React-style widgets + hot loading) may swing me in the other direction once I have a bit more experience.

Apps I Would Consider Using It For

  • Apps that need multiple platforms, but have a limited budget.
  • Brand-heavy apps that eschew native platform conventions in favour of a custom UI
  • Proof of concept apps
  • Short lifetime apps that need to be built quickly, but not necessarily maintained
  • My personal projects
  • Games

In Closing

Wow, this turned out to be much bigger than I thought! Hopefully I’ve covered a lot of topics that we should be thinking about when considering a new technology such as Flutter.

Of course, a lot of my summaries are subjective and prey to my personal biases and preferences. I do hope, though, that all of the information I’ve discussed is accurate. Please let me know if I’ve missed something or if you have thoughts you’d like to share.

I can’t wait to see what Google announces in a few weeks at Google I/O!!

Linkly #6 – Powerful Talks

Linkly is a curated list of interesting products, topics and talking points from the world of design and technology.

It is said that the pen is mightier than the sword. That a person can change opinions and influence people far more effectively with the written word than with brute force and a sword. In the modern day with an endlessly flowing stream of information right at our fingertips the opinions that stand out from the pack are those that are insightful and engaging, that reach into the lives of their audience and elicit a truly emotional response. 

Video does a brilliant job of creating a connection between the viewer and the speaker. It provides a far more human element to the exchange of information that respects the meaning and the value of the speaker’s intentions. This week instead of linking to articles from around the web that will inevitably end up at the bottom of your ‘Read it Later’ pile, take the time to watch these powerful and insightful talks about design and technology. 

Ken Robinson: Do Schools Kill Creativity?

From the day that you’re born, you’re thrust into long, tough and hard years of education. Without consent, every child goes through pre-school, primary school, high school. It is assumed knowledge that school is what is best for kids. Ken Robinson goes down the path less travelled and asks the question, “Do schools kill creativity?” 

Simon Sinek: How great leaders inspire action

If there is one talk that you must watch in your life, and that has the potential to make the biggest impact on your work it’s Simon Sinek’s talk. He proposes the simple model for leadership, and the framework around which you can truly give people what they want, by asking ‘Why?’

Ira Glass on Storytelling

Nothing comes easy, especially mastering your craft. In this typographic masterpiece world renowned radio host of the popular podcast, This American Life, explains the 10,000 hours principle. That it takes approximately 10,000 hours of hard work, passion and persistence to become a leader in your field.

Sheryl Sandberg: Why we have too few women leaders

Facebook’s COO delivers a brilliant talk on why less women reach the top of their professions. She offers powerful advice to women aiming to break form and strive to be leaders. A fantastic talk that is well worth taking the time to watch closely and that will open your mind to problems you didn’t know existed.

Jon Ronsen: How One Tweet Can Ruin Your Life

From the man who brought you, The Psychopath Test, Jon Ronson takes a look at public shaming, and the role social media plays in the problem. He examines the problem and its effects on society as a whole.

Words are a powerful way to convey meaning and express ideas. Even more expressive, engaging and effective is the human voice. Standing on stage in the spotlight, with hundreds of people hanging on your every word. If you’re inspired by these talks you too can share your thoughts, and present them publicly, and potentially change the way people think about the world around them.

Linkly #4 – WWDC Predictions

Linkly is a curated list of interesting products, topics and talking points from the world of design and technology. Last week was all about Google, so we only thought it was fair to give Apple a go too. WWDC is only a few weeks away and we’ve curated a list of predictions our team at Bilue are hoping will turn into a reality at this years event.


iOS 10 Concepts

Macstories have published this concept video for iOS 10. Some of our fav ideas include the Control Centre updates, system dark mode,  revamped Messages app and improved iPad multitasking!



Siri Smarts

There is speculation that Apple is planning on releasing a Siri SDK to allow developers to tap into Siri functionality and open up clever possibilities for apps inside the iOS ecosystem. We’re really interested in seeing how this might change how people interact with their devices and if talking to Siri in public becomes more conventional.



iPhone 7 and iOS 10 rumours

Zac and Benjamin from Happy Hour have released this podcast where they talk through iPhone 7 and iOS 10 rumours. Also mentioned is Apple Car, how smart connectors could work with the phone, removing the iPhone home button and more! An easy listen where they talk through some interesting ideas.



Apple Music Changes

This article makes mention of a colour scheme change from magenta to black and white, larger album artwork images, smart playlist functionality and a moments style feature where you can track what music you were listening to at particular points in time or place. Apple loves to pull the heart strings!

We’re all super excited to see what is unveiled at WWDC. If you have more to add on the topic, we’d love to hear your thoughts and predictions!


Try! Swift 2016

On Wednesday 2nd March – Friday 4th March, I attended the first Try! Swift developers conference in Tokyo, Japan. As Apple’s new programming language begins to grow and mature it is now receiving a large amount of attention throughout the developer community. This conference was a great opportunity for developers of the iOS, tvOS, watchOS and Mac OS X platforms to present on the ways they are pushing the limits of the language. It has opened up many unique discussions on the ways the language itself can be improved, some of the drawbacks that exist and most importantly the best practices that have revealed themselves already within the community.

Leaving from Terminal 2 at Sydney Airport with a conference ticket I had only received days earlier off the waiting list, I had no idea of the experience I was in for and the great people I was about to meet. I sat contently in my seat somewhat rushed, fearful, nervous yet excited for my first trip to Tokyo.

Sydney Airport

We have already begun using Swift at Bilue with many of our clients and of course on our own internal projects. As a team we have been pushing ourselves forward, learning new things and working extremely hard to bring each other up to scratch on everything that Swift introduces. I’d decided that attending the conference was a great way to extend my learning and to exchange ideas with some of the leading developers from across the world.

It turned out that Tokyo was an amazingly beautiful place that seemed to deeply align with my passions on so many different levels. On the days leading up to the conference I found time to explore a few different areas, most notably my favourite place – Omotesando. I loved the quiet atmosphere and the subtle nature that seemed to somehow augment the buildings and the cityscape. I quickly learned this to be home to some of the finest coffee that Tokyo has to offer, including Blue Bottle Aoyama which was as amazing as its San Fransisco counterpart except without the long lines and hot sun.

Cherry Blossoms

For us Swift augments our design-led approach to building inspired products. It allows us to apply the core idioms of the Swift language into writing safer, more reliable and less error-prone code. Essentially, by writing Swift we can be more certain that our software behaves exactly the way we expect it to. By taking advantage of Swift’s protocol oriented approach to application architecture we end up building products that are far more maintainable for our clients long after we’ve touched them.

At the conference located in Shibuya Mark City, I attended countless talks that were each in their own way both insightful and intriguing. On the first day Syo Ikeda presented a great talk which dived deep into the broad Swift Ecosystem. Syo outlined the most popular frameworks, libraries, resources and tools that any decent Swift developer would need to know about. We also heard Laura Savino explore the intricacies and cross-overs of learning a new language, whether it be a new programming language or a spoken language. Gwendolyn Weston quickly wowed the audience with her well received and incredibly detailed use of Pokemon as an example of Swift Type Erasure.

Blue Bottle Coffee
Tokyo Dome Baseball
Tokyo Sunset

One of the biggest highlights of my trip to Tokyo was being able to find and attend a Yomiuri Giants exhibition game played at Tokyo Dome. Despite all of the hilariously cruel difficulty I went through to get my ticket printed at the convenience store, I managed to get in. I played baseball when I was younger, and I’ve seen a game in San Fransisco, but now I know that baseball in Tokyo is like none other. Another memorable moment took place on the Tuesday evening before the conference, many of the speakers and attendees organised a visit to Roppongi Hills. At the top of the Tokyo City View we watched as the sun set over the skyline and this view was nothing short of breathtaking.

On the second day Adam Bell from Facebook asked a really great question, “When was the last time you used an app that felt surreal, or broke the laws of physics?” He presented his doubts about the plain, flat and lifeless modern iOS application and then discussed the ways prototyping can be used to implement rich, interactive and immersive animations using Swift.

Daniel Eggert explored how Swift allows developers to breathe an entirely new life into old and rigid but still tried and tested Cocoa APIs such as Core Data. Later that day Chris Eidhof similarly presented a more Swift-y approach to UITableViewControllers and demoed a really fun and unique keyboard shortcut animation technique.

Fish Market

Ridiculously early (at about 5:00am) on Thursday morning a friend and I woke up and made the trek down to the Tsukiji fish market. I’d been told that this well known fish market will be relocated really soon, so I was really glad that I took the chance to go while I could. It was a fast and intense experience with motor scooters carrying fish barrels zooming past us, it was really obvious that we had no idea where we were or what to do. Nonetheless I managed to take some really nice photos that made the early morning well worth it.

A standout talk on the final day of the conference was the excellent talk presented by Jesse Squires from Instagram on contributing to Open Source Swift. Jesse gave a really in-depth and well thought out, yet clear and simple understanding of the Swift project structure. He told us exactly how the Swift code we write in Xcode is compiled into a binary for release to the App Store. He provided a perfect guide and recommendation on contributing to the underlying Swift library at any experience level and with any skill set. Most importantly he outlined the importance of making Swift into a language that the community as a whole can enjoy and use productively.

Swift is more than a programming language. Swift is a community!

Another great talk was Ash Furrow’s overview of the Artsy approach to testing. Ash breaks down the different approaches to each of their apps based on which approach (or lack of!) they took and how it affected the team and the product itself. I really appreciated seeing Ash give this talk and outlining the balance that is required when implementing BDD (Behaviour Driven Development) or TDD (Test Driven Development) with tight deadlines and uncontrollable circumstances. He mentioned the Snapshot approach to testing, which is definitely something that I will be taking a look into and experimenting with.

Group Photo
Wine Salesmen
Chris and Phill
Lee and Phill

There is no other way to say it than this – I met so many amazing developers and people at Try! Swift that I just know I’m going to be really great friends with for the rest of my life. It underlines exactly why I chose to become a software developer, and exactly why I believe software creates opportunities that make the world a much better place to be.

A takeaway for me from the conference was that for the foreseeable future Swift is at the bleeding edge of the Apple Developer Community. And as has come to be expected, Swift is taking shape in the form of a strong, powerful and great community. There are so many developers learning Swift together right now, each and every one pushing the boundaries of the language making it a greater language to build amazing things with over time. Swift has the potential to greatly improve our development experiences at Bilue as well as to ensure that the inspired products that we create truly fulfil their purpose for the people that use them.

Daigoji Temple

We intend to continue working hard on writing Swift and will post some of our thoughts, experiences and code here as we go. Thank you to everyone who organised Try! Swift, which turned out to be an amazing conference in a beautiful city bringing together some of the smartest minds from around the world.



New Call-to-action


The State of iOS Dependency Management

Dependency management is a tricky problem to solve, even more so on iOS projects where we have to concern ourselves with things like code signing, embedded binaries, and so on. In recent years, a couple of solutions to this problem have presented themselves, each with different approaches and guiding philosophies, and each with their own tradeoffs to consider.

Manual Integration

There’s a lot of ways to integrate third party dependencies without using third-party tools. Most OSS projects use Git for source code management these days, so we can include those dependencies using Git submodules. Failing that, we can simply download the latest snapshot of a project and copy it into our project’s source tree.

With some basic knowledge of setting up Xcode projects, this solution actually gets us pretty far. It’s not the simplest or easiest approach, but it has its advantages. For one, not relying on third-party tools mean other team members can easily build your project without installing additional tools. This method is also the most resistant to breaking changes introduced in newer versions of Xcode, as there’s no waiting on a third-party to update their tools.

However we quickly run into issues as we add more dependencies to our project, especially when those themselves also have dependencies. Eventually we’re going to run into a case where two dependencies require two different versions of a library, and at that point we have to do a lot of messy manual resolution. Take the following example:


Here we have a project that uses ReactiveCocoa and the (somewhat less well-known) ReactiveCocoaLayout library. In this situation, both our project and ReactiveCocoaLayout depend on different versions of ReactiveCocoa, so in a manually integrated project we have to do the hard work of resolving this conflict ourselves.

Beause of this, and various other problems, a new solution soon arrived.


CocoaPods is a Ruby gem that handles the task of resolving dependencies for us, generating an Xcode project that builds those dependencies, and generating an Xcode workspace that lets us integrate them into our project. To include a dependency through CocoaPods, someone has to write a Podspec that describes how to build the framework, and what other dependencies it has. CocoaPods keeps a public repository of these Podspecs for open-source frameworks, and you can specify your own sources for private Pods.

If we wanted to recreate our example from the previous section, we’d create a Podfile in the root of our project with the following contents and then run pod install:

source ''

platform :ios, '8.0'

pod 'ReactiveCocoa'
pod 'ReactiveCocoaLayout'

This approach is very much inspired by tools like RubyGems, and it has a lot of advantages. For one, it makes integrating dependencies extremely easy by taking over the duty of configuring your Xcode project for you. It also aids in discoverability, with providing a searchable repository of open-source pods, and publishing easily searchable documentation.

It’s also widely adopted, with most frameworks offering official Podspecs, and those that don’t often having community-maintained specs that are kept relatively up to date. This popularity also means that when you do run into issues with CocoaPods, you’re rarely the first to and there’s likely StackOverflow answers already out there to solve your problem.

For authors of libraries, it can also reduce the maintainence burden of updating projects to build on new versions of Xcode, as CocoaPods handles the entire build process and updates whenever new Xcode versions are released. This does however mean that projects which also want to build without CocoaPods need to specify build steps in multiple places.

However, CocoaPods’ ease of use comes at the cost of quite a bit of complexity and a certain loss of flexibility in how you set up your project. For more experienced developers that feel they know how best to set up an Xcode project, the way CocoaPods wrests that control away from you can be frustrating. For library authors, it can also seem redundant to have to create a Podspec that mostly just reiterates information that’s already contained in Git and Xcode.

Finally, CocoaPods was initially designed to build static libraries and for a long time lacked any sort of support for frameworks. Initially, this was something only OS X developers really cared about as iOS didn’t have framework support prior to iOS 8. However, with iOS 8, not only were frameworks supported, but they became a requirement for using Apple’s new Swift programming language. Despite framework support eventually coming to CocoaPods, it has always felt like something of a second-class citizen.

So along came another solution.


Carthage is described by its creators as “ruthlessly simple dependency management.” Its aim is to act as a simple coordinator between Git and Xcode, that picks compatible versions of dependencies, checks those dependencies out with Git, and then builds frameworks with Xcode.

To recreate our example project with the ‘standard’ Carthage setup, we would create a Cartfile at the root of our project with the following contents and then run carthage bootstrap:

github "ReactiveCocoa/ReactiveCocoaLayout"
github "ReactiveCocoa/ReactiveCocoa"

This would pull down our dependencies and build them as frameworks, but we would still need to manually integrate them. To do this we’d simply add references to them in our Xcode project and add them to the linked frameworks section of our target’s build settings.

Compared to CocoaPods, it’s a much simpler tool, though perhaps not as easy to use. Carthage does not integrate dependencies into your project in the same way CocoaPods does, instead leaving that task up to the developer. The upside of this is increased flexibility in how you integrate dependencies: whether by embedding the built frameworks, or by creating a workspace that includes all the cloned Xcode projects of your dependencies. In fact, Carthage can add all your dependencies as Git submodules, removing the need for other devs to install Carthage at all.

For library authors, supporting Carthage couldn’t be easier. You simply need to make an Xcode project that can build your framework, and then share the build schemes contained in that project. Compared to CocoaPods’ spec-based approach, this is refreshingly simple. There’s no need to submit a spec to any sort of central repository, instead users simply refer to a GitHub repo or Git URL in their Cartfile. This decentralised approach also simplifies the use of private frameworks and forks.

Carthage also tends to speed up builds in a few key ways. Firstly, frameworks are built once when you bootstrap or update your project, and then simply embedded on subsequent builds. Secondly, Carthage integrates with GitHub’s Realeases feature to download precompiled frameworks wherever possible.

Compared to CocoaPods, Carthage doesn’t have quite as much traction. There’s still the occasional project out there that doesn’t expose any shared build schemes, but this is usually simple to resolve with a quick pull request. Carthage also doesn’t help with discovering new libraries to use, your best bet there is to search GitHub.

Swift Package Manager

Announced as part of Swift going open-source, the Swift Package Manager, or swiftpm, marks the first time we’ve had something akin to an official dependency manager. It’s perhaps a little soon to say too much about swiftpm, it’s still very early and not officially released, but the current implementation and the package manager community proposal provide a lot of food for thought.

With swiftpm, developers create a Package.swift file in the root of their project that describes their project and its dependencies. swiftpm then resolves those dependencies based on git tags, pulls them down, and builds them as static libraries.

The Swift Package Manager is similar in certain aspects to both Carthage and CocoaPods. Like Carthage, it uses a decentralised approach to dependency resolution, and builds those dependencies as standalone binaries. Like CocoaPods, it uses specification files to define libraries and their dependencies — though this perhaps makes more sense for swiftpm, as it has to run on platforms where Xcode and by extension xcodebuild don’t exist.

As swiftpm builds static libraries as opposed to frameworks, there’s currently no way to include resources like XIBs or image files in a library. However, this is highlighted by the fairly in-depth package manager community proposal as something to add in future releases, alongside numerous other features that would make it more feasible for iOS projects.

In fact, looking at the proposals set forth in that document, it seems clear that the Swift Package Manager will eventually become the de-facto solution for dependency management on iOS projects. Just not today.

Which One Should You Use?

As with most things, the answer is ‘it depends’. If you want to easily bootstrap a new project, CocoaPods will take care of most of the work for you. If you want more flexibility in how you set up your project, or you want to more easily use private libraries that aren’t in a central repo, Carthage is probably the better option.

Bilue’s Swift Style Guide



Today we’re open-sourcing our internal Swift style guide. This is something we’ve been working on in an attempt to codify best practices and improve codebase consistency within the company, and it’s something we’d love to have the Swift community’s feedback on.

The guide is a work in progress that’s intended to evolve as we undertake more and more Swift projects. We’re still in the early days of Swift development, and what constitutes ‘idiomatic Swift’ is still in a state of flux. As both we at Bilue and the community at large decide on new best practices in Swift development, we want to keep our guide up to date with those decisions.

Why have a swift style guide?

As the number of people working on a codebase increases, you’re more and more likely to encounter developers with differing opinions on how to write code. This can be about anything from tabs vs. spaces to things like when it’s appropriate to use computed properties.

These differences in opinion can lead to long, drawn out debates over aesthetics during code reviews. Even once a consensus is reached, it’s rarely enforced across the codebase. This approach also means the same decisions have to be made for every new project, and there’s very little consistency between the projects themselves.

With a style guide, these decisions can be made once, recorded in a central repository, and then referred to by all of the projects within our company. When a debate over style comes up during a code review, developers can simply refer back to the style guide. If a developer needs to move from one project to another, they can be assured that they won’t have to learn a whole host of new conventions and habits.

By codifying best practices in this way we improve consistency, reduce debate, and raise the general quality of all of our codebases.

How we built our style guide

Rather than start our guide from scratch, we’ve decided to fork GitHub’s style guide and modify it for our own use. This has saved us a great deal of groundwork and GitHub’s guide makes for a great starting point. We’ve made some minor changes to the original content of that guide, but so far most of our changes have been additive.

Our guide is broken up into a series of guidelines, each with a brief summary, a more detailed example to show how that pattern would be implemented, and a rationale that explains the reasoning behind that guideline. These guidelines are intended to encompass patterns that can be applied across any codebase to improve the clarity and decrease the likelihood of programmer errors.

New guidelines are added by opening a pull request on our core repo, and we generally spend some time refining new guidelines either in PR comments, or through discussion in our #swift Slack channel.

Our Swift style guide is still in its early days, but already it has sparked a lot of valuable discussion within our company. It has started pushing us towards a more consistent, company-wide coding style that makes it easier to move between projects, and is raising the baseline level of quality across each of our codebases.

If you’re looking to implement a style guide at your own company, or within an open-source organisation, our guide is under a liberal Creative Commons license and we’re accepting contributions.

Configuring watchOS 2 Targets


To save people some headaches in the future when they have to work on watchOS 2 projects, here’s exactly how you need to configure watch targets to avoid the dreaded LaunchServicesError error 0.

App Groups
You’ll need to create a new App Group so that your watch extension can communicate with the base app. You can name this group whatever you want, but the ID should be your base app’s bundle ID prefixed with .group. So for an app with the bundle ID of the group ID should be

App IDs
This is the part that caused me the most headaches. The ID of an embedded bundle on iOS must be prefixed with the bundle ID of their parent bundle. What makes this confusing in watchOS 2 is the way the directory structure of the bundle has changed. In watchOS 1, both your watch app and watch extension bundles would be embedded directly into the main app bundle. However in watchOS 2, the watch extension is now embedded inside the watch app, which in turn is embedded in the main app bundle.
So following Apple’s rules around embedded bundles’ IDs, that means our watch app’s bundle ID should be prefixed with the main app’s bundle ID, and the watch extension’s bundle ID should be prefixed with the watch app’s bundle ID. What this looks like in practice is as follows:

  • Main App —
  • Watch App —
  • Watch Extension —

All of these app IDs must have the App Groups capability enabled, with the group configured to be the one we set up earlier.

Provisioning Profiles
These are pretty easy, just create provisioning profiles for each of the 3 app IDs we’ve created. To run your app on a real watch, you’ll need to include both the watch itself and the paired iPhone in all three of these provisioning profiles.

Xcode Targets
The watch extension and watch app should be built with the profiles and app IDs we set up for them. On top of that, there’s a whole bunch of things that can go wrong in your target configuration that’ll generate unhelpful errors. Here’s some things to check if that happens:

  • The version numbers and build numbers of the main app, watch app, and watch extension must all be identical.
  • In the watch extension’s Info.plist file, the value of NSExtensionNSExtensionAttributesWKAppBundleIdentifier must match the CFBundleIdentifier of the watch app.
  • In the watch app’s Info.plist the value of WKCompanionAppBundleIdentifier must match your main app’s CFBundleIdentifier.

Contact Info

Level 1 6 Bridge Street, Sydney, NSW, 2000

Level 1 520 Bourke Street, Melbourne, VIC, 3000

Copyright 2018 Bilue Pty Ltd ©  All Rights Reserved