In this mini-series, you will get the perspective of an experienced native iOS developer who has spent almost one-year building and releasing a Flutter app. Of course, the presented topics are purely subjective — your experience may vary.
When the team decided to switch to Flutter, no one had much experience writing code in Dart or used Flutter widgets to compose UI. The following insight was gained during the development from a novice to becoming a somewhat experienced Flutter developer.
Spoiler alert: using Flutter is a successful environment for us as we use it to continue building our mobile app. But where there is light, also a shadow! This series is about both.

If you’re interested in seeing what we have built? Check it out with this link.

In this part, I’m talking about the good parts. Look out for parts one and two about the good and bad of developing Flutter applications.

The Ugly

Exceptions and Errors

Things might go wrong. Almost all programming languages provide ways for error handling. Dart is no exception here, allowing to throw something that you can catch further up in the call hierarchy.

I would assume that only exceptions (or whatever your programming language is calling them) can be thrown. Not with Dart. Everything can be thrown: strings, integers, even custom objects. A poor design choice! There is a linter rule for disallowing throwing of any object. But why allow it in the first place?

Besides Exceptions there are also Errors. Exceptions indicate failures at runtime that are part of normal operation, while errors indicate failures the programmer did. That is fine! But by default, all try/catch statements will catch both errors and exceptions, making it very easy to ignore or shadow programming errors, having them look like normal runtime failures. There are again linter rules for catching only exceptions, but why not have sensible defaults for try/catch that would require adding code to catch errors (or anything else that might get thrown)?

Native Plugins

Coming from native development and seeing the quality of native code written to bridge functionality to Flutter makes me shiver.
I’m not going to point fingers, but things look bad: from missing error handling to having many warnings to comparing pointer addresses instead of string content. Sure, people writing those plugins might only have limited experience with native mobile development, nevertheless including those plugins come with a risk of breaking things.
We resorted to writing some native plugins on our own, making sure they actually work and are up to our standard.


Flutter is no silver bullet when it comes to mobile app development. Nevertheless, having limited resources or small to medium projects, I recommend looking into Flutter. With an active community around it and good enough widgets, libraries and documentation, you can get pretty far. You might save a lot of time not having to write two separate code bases for Android and iOS. But keep in mind the more complex setups, that also want to take in platform-specific behavior, might give you a hard time and require workarounds and a little native code for support.