Mobile Development 16 min read

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.

Huajiao Technology
Huajiao Technology
Huajiao Technology
Comparing SwiftUI and Flutter: Declarative UI Approaches for Mobile 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.

Fluttermobile developmentcross-platformstate-managementSwiftUIDeclarative UI
Huajiao Technology
Written by

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.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.