iOS Developer Switching to Flutter: What I Wish I Knew Sooner
The Context
After 6 years of building iOS apps with Objective-C and Swift, I joined Jio Health in 2019. The team was building an ecosystem of healthcare apps: patient app, doctor app, internal tools. Maintaining separate iOS and Android codebases for each was unsustainable, so we picked Flutter.
I was skeptical. I'd watched frameworks that promised one codebase for both platforms come and go. Flutter was different, and here's what surprised me.
Surprise #1: The Widget System is Actually Better
Coming from UIKit and its imperative layout (addSubview, NSLayoutConstraint, Auto Layout), Flutter's declarative widget tree felt alien.
In UIKit:
- Create a view
- Configure its properties
- Add constraints
- Handle state changes imperatively
In Flutter:
- Describe what the UI should look like given the current state
- The framework handles the rest
Going from "modify the view" to "rebuild the view" was the hardest part. Once it clicked, I was building UI 2 to 3 times faster than in UIKit.
Tip for iOS developers: Flutter widgets work like SwiftUI views. If you haven't used SwiftUI, start there; it makes the Flutter transition smoother.
Surprise #2: Dart is Not a Downgrade
I expected Dart to be a step backwards from Swift. It isn't:
- Null safety: (since Dart 2.12): similar to Swift's optionals
- Async/await: cleaner than Swift's completion handlers (though Swift now has structured concurrency)
- Extensions: works just like Swift extensions
- Mixins: more powerful than Swift's protocol extensions in some ways
What I miss from Swift: enums with associated values, pattern matching, and the expressiveness of the type system. But Dart gets the job done.
Surprise #3: State Management is a Whole World
iOS has established patterns: MVC, MVVM with Combine or RxSwift, VIPER. Flutter has setState, Provider, Riverpod, BLoC, GetX, MobX, Redux.
We settled on BLoC/Cubit for complex features and Provider for simpler ones:
- BLoC enforces separation of concerns through events and states
- You can test the business logic without the UI
- It maps well to the reactive programming I knew from RxSwift
Tip for iOS developers: Coming from RxSwift, BLoC feels familiar; the streams concept is the same.
Surprise #4: Hot Reload Changes Everything
The iOS cycle is build, run, wait. Even with incremental builds, that's 10 to 30 seconds per change. Flutter's hot reload updates the UI in under a second and preserves state.
It changes how you develop:
- You experiment more freely
- You iterate on UI details faster
- You catch layout issues immediately
- You stay in flow longer
I think hot reload matters more than shipping to both platforms.
Surprise #5: Platform Channels Are Straightforward
My biggest fear was losing access to native iOS APIs. Platform channels made it easy:
- HealthKit integration: a thin Swift layer called from Dart
- CallKit: native call UI in Swift, events bridged to Flutter
- WebRTC: a Flutter plugin with custom native modifications
- APNS: push notifications handled natively, events forwarded to Dart
The pattern is always the same: write the native code in Swift/Kotlin, define a channel, serialize the data.
What I Still Miss from Native iOS
Flutter isn't perfect:
- Animations: Core Animation gives you control down to the pixel. Flutter's system is good but different.
- Platform feel: despite Material and Cupertino widgets, Flutter apps don't feel 100% native. Close, not identical.
- Xcode Instruments: DevTools are improving, but Instruments is still better for profiling.
- App size: our patient app is about 15 MB larger than it would be as a pure Swift app.
My Advice for iOS Developers Considering Flutter
- Don't fight the framework.: Embrace the declarative approach instead of making Flutter act like UIKit.
- Learn Dart properly.: Spend a weekend on null safety, futures, streams, and isolates.
- Start with BLoC or Riverpod.: Skip setState for anything beyond a prototype.
- Keep your native skills sharp.: You'll need them for platform channels, debugging, and platform behavior.
- Build something real.: Tutorials won't give you production experience. Pick a side project and ship it.
It took about 2 months to feel productive and 6 months to feel confident. We now ship features to both platforms at once with a single team.