Comparing SwiftUI and Flutter: Declarative UI Approaches for Mobile Development
This article compares Apple’s SwiftUI and Google’s Flutter declarative UI frameworks across development environment, UI components, layout, navigation, native integration, and state management, highlighting their similarities, differences, code complexity, and maturity for cross‑platform mobile app development.
What is SwiftUI
At WWDC 2019 Apple announced SwiftUI, a declarative UI framework for building apps across iOS, iPadOS, macOS, watchOS, and tvOS with a single codebase.
Developers are excited because SwiftUI brings modern declarative programming to Apple platforms, offering simplified code, declarative syntax, higher productivity, hot‑reloading, and cross‑platform capabilities.
What is Flutter
Flutter, released by Google two years earlier, is a UI framework that enables fast development of high‑performance native‑looking apps for iOS and Android. It is free, open‑source, and supports a rich set of widgets.
What is Declarative UI
Traditional imperative UI code (e.g., UIKit’s UIViewController) mixes UI layout, event handling, and business logic, often resulting in large, hard‑to‑maintain files. Declarative UI separates the description of the UI from the underlying platform, allowing the framework to update the view automatically when bound state changes.
In an imperative flow a login sequence requires explicit view creation, event handling, and state checks. In a declarative flow the UI is described as a function of state, and the framework recomposes the view when the state changes.
Development Comparison Using the "Landmarks" Sample App
The article uses Apple’s SwiftUI "Landmarks" tutorial and a Flutter port of the same app to compare the two frameworks.
Development Environment
SwiftUI development is done in Xcode, which provides a live preview canvas that updates instantly as code changes.
Flutter development can be done in Android Studio or Visual Studio Code; both show project files, code editor, and a widget outline, but lack the live preview feature.
UI Components
SwiftUI – View
Custom views conform to the View protocol and implement a body property. Example:
struct ContentView: View {
var body: some View {
Text("Hello World!")
}
}Flutter – Widget
All UI elements inherit from Widget . A stateless widget example:
import 'package:flutter/material.dart';
class ContentView extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Center(
child: Text("Hello World!"),
);
}
}Layout
SwiftUI’s HStack , VStack , and ZStack correspond to Flutter’s Row , Column , and Stack respectively.
Example of a list row in SwiftUI:
HStack {
landmark.image.resizable().frame(width: 50, height: 50)
Text(landmark.name)
Spacer()
if landmark.isFavorite {
Image(systemName: "star.fill")
.imageScale(.medium)
.foregroundColor(.yellow)
}
}Equivalent Flutter row:
Row(
children:
[
Image.asset('assets/${landmark.imageName}.jpg', width: 50.0),
SizedBox(width: 16),
Text(landmark.name, style: TextStyle(fontSize: 16)),
Expanded(child: Container()),
landmark.isFavorite ? StarButton(isFavorite: landmark.isFavorite) : Container(),
Icon(Icons.arrow_forward_ios, size: 15.0, color: const Color(0xFFD3D3D3)),
],
)Lists
SwiftUI uses List with ForEach to generate rows:
List {
ForEach(landmarks) { landmark in
LandmarkRow(landmark: landmark)
}
}Flutter uses SliverList with a builder delegate:
SliverList(
delegate: SliverChildBuilderDelegate(
(context, index) {
final landmark = landmarks[index];
return LandmarkCell(landmark: landmark);
},
childCount: landmarks.length,
),
)Navigation (Page Transitions)
SwiftUI relies on NavigationView and NavigationLink :
var body: some View {
NavigationView {
List {
ForEach(userData.landmarks) { landmark in
NavigationLink(destination: LandmarkDetail(landmark: landmark)) {
LandmarkRow(landmark: landmark)
}
}
}
.navigationBarTitle(Text("Landmarks"))
}
}Flutter uses Navigator.push with a Route :
SliverList(
delegate: SliverChildBuilderDelegate(
(context, index) {
final landmark = landmarks[index];
return LandmarkCell(
landmark: landmark,
onTap: () {
Navigator.push(
context,
Route(builder: (context) => LandmarkDetail(landmark: landmark)),
);
},
);
},
childCount: landmarks.length,
),
)Native Functionality
SwiftUI integrates Apple’s MapKit via UIViewRepresentable :
struct MapView: UIViewRepresentable {
var coordinate: CLLocationCoordinate2D
func makeUIView(context: Context) -> MKMapView { MKMapView(frame: .zero) }
func updateUIView(_ view: MKMapView, context: Context) {
let span = MKCoordinateSpan(latitudeDelta: 0.02, longitudeDelta: 0.02)
let region = MKCoordinateRegion(center: coordinate, span: span)
view.setRegion(region, animated: true)
}
}Flutter uses the google_maps_flutter plugin:
Widget _mapView() {
return GoogleMap(
mapType: MapType.normal,
initialCameraPosition: CameraPosition(
target: LatLng(landmark.coordinates.latitude, landmark.coordinates.longitude),
zoom: 13.70,
),
myLocationButtonEnabled: false,
onMapCreated: (GoogleMapController controller) {
_controller.complete(controller);
},
);
}State Management
SwiftUI marks stateful data with @State and binds UI controls directly:
struct LandmarkList: View {
@State var showFavoritesOnly = true
var body: some View {
NavigationView {
List {
Toggle(isOn: $showFavoritesOnly) { Text("Favorites only") }
ForEach(landmarkData) { landmark in
if !showFavoritesOnly || landmark.isFavorite {
NavigationLink(destination: LandmarkDetail(landmark: landmark)) {
LandmarkRow(landmark: landmark)
}
}
}
}
.navigationBarTitle(Text("Landmarks"))
}
}
}Flutter updates UI by calling setState inside an event handler:
CupertinoSwitch(
value: _showFavoritesOnly,
onChanged: (state) {
setState(() { _showFavoritesOnly = state; });
},
)Conclusion
The comparison shows that both SwiftUI and Flutter share many declarative UI concepts, but SwiftUI generally requires less boilerplate and results in more concise code because it is tightly integrated with Apple’s ecosystem. Flutter, being open‑source and cross‑platform, offers greater customizability at the cost of higher code volume and complexity.
SwiftUI is still early (beta at the time of writing) and limited to iOS 13+ devices, whereas Flutter has matured over several years with broad device support.
References
Apple SwiftUI tutorials and documentation, the Flutter Landmarks GitHub repository, and various comparative articles.
Huajiao Technology
The Huajiao Technology channel shares the latest Huajiao app tech on an irregular basis, offering a learning and exchange platform for tech enthusiasts.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.