The Flutter → iOS Mental Model
As a Senior Flutter Engineer, you already know how to build apps. You just speak a different dialect. This guide maps your existing knowledge to the Apple ecosystem.
1Core UI Concepts
Rendering & Widgets
Flutter
iOS (Swift/SwiftUI)
Key Differences
Widget
View (SwiftUI) / UIView (UIKit)
SwiftUI Views are value types (structs), just like Flutter Widgets are immutable descriptions.
build() method
body property
In SwiftUI, `body` is a computed property that returns `some View`. It’s invoked whenever state changes.
StatelessWidget
View (struct)
A simple SwiftUI View without @State properties is effectively stateless.
StatefulWidget
View + @State
State is held in property wrappers like @State or @StateObject, not a separate State class.
Context (BuildContext)
Environment / KeyPath
SwiftUI uses the Environment to pass data down. No direct BuildContext equivalent is needed for tree traversal.
Critical Difference: The "State" Class
In Flutter, `StatefulWidget` creates a separate `State` class that persists. In SwiftUI, the `View` struct itself is destroyed and recreated, but the `@State` properties are managed by the runtime and persist outside the struct.
2State Management & Logic
Business Logic Components
Flutter
iOS (Swift/SwiftUI)
Key Differences
Cubit / BLoC
ViewModel (ObservableObject)
iOS uses MVVM standardly. The ViewModel holds published properties that views observe.
State Class (BlocState)
Published Properties
Instead of emitting a new State object, specific properties are marked @Published to trigger UI updates.
Stream<State>
Combine Publisher / AsyncSequence
Combine is the closest analogue to RxDart/Streams. Swift Concurrency (Async/Await) is replacing it for simple flows.
BlocProvider
@StateObject / @EnvironmentObject
Dependency injection into the view hierarchy.
BlocListener
.onChange(of:) / .onReceive()
React to side effects (navigation, snackbars) when value changes.
3Concurrency & Threading
Async Operations
Flutter
iOS (Swift/SwiftUI)
Key Differences
Isolate
Grand Central Dispatch (GCD) / Swift Task
iOS usually shares memory (managed by ARC), unlike Isolates which do not share memory. Swift 6 Actors isolate state similarly to Isolates.
Future<T>
Task<T, Error> / async function
Modern Swift uses async/await syntax almost identical to Dart.
compute() / Isolate.run()
Task.detached / DispatchQueue.global()
Offloading intensive work to background threads.
Next Section
Widget-to-Swift MapProject Structure
Files & Entry Points
Flutter
iOS (Swift/SwiftUI)
Key Differences
lib/main.dart
@main App.swift
The entry point. SwiftUI uses the @main attribute.
pubspec.yaml
Project.xcodeproj / Package.swift
iOS config is often binary (managed by Xcode), though SPM is text-based.
android/ & ios/ folders
Top level files
iOS IS the native project. No separate runner folder.
Assets (pubspec defined)
Assets.xcassets
iOS has a visual catalog for images, colors, and icons.
Dependency Management
Flutter: Pub
- pubspec.yaml: Central declarative file.
- pub.dev: The central repository.
- Lockfile: pubspec.lock.
iOS: The Mix
- Swift Package Manager (SPM): The modern standard. Defined in `Package.swift` or via Xcode GUI.
- CocoaPods: Old standard. Uses `Podfile` and ruby. Still used by many big libs (Firebase, RN).
- Carthage: Manual binary Framework linking. Rare now.
Build Environments
Flavors vs Schemes
Flutter
iOS (Swift/SwiftUI)
Key Differences
--flavor dev
Build Configuration (Debug/Release)
iOS has strict Debug vs Release modes at the compiler level.
main_dev.dart
Schemes (Product -> Scheme)
Schemes define what config to run and what environment vars to set.
.env files
.xcconfig files
Use xcconfig to inject variables into Info.plist or Build Settings.