Sitemap
The Airbnb Tech Blog

Creative engineers and data scientists building a world where you can belong anywhere. http://airbnb.io

Unlocking SwiftUI at Airbnb

10 min readSep 21, 2023

--

Evaluating and Planning for SwiftUI

Enabling SwiftUI

Design System

public protocol FlexibleSwiftUIViewStyle: DynamicProperty {
/// The content view type of this style, passed to `body()`.
associatedtype Content
/// The type of view representing the body.
associatedtype Body: View
/// Renders a view for this style.
@ViewBuilder
func body(content: Content) -> Body
}
public struct DefaultStepperStyle: DLSNumericStepperStyle {
public var valueLabel = TextStyle…


public func body(content: DLSNumericStepperStyleContent) -> some View {
HStack {
Button(action: content.onDecrement) { subtractIcon }
.disabled(content.atLowerBound)
Text(content.description)
.textStyle(valueLabel)
Button(action: content.onIncrement) { addIcon }
.disabled(content.atUpperBound)
}
}
}
Example stepper created from the default style properties
DLSNumericStepper(value: $value, in: 0...)
.dlsNumericStepperStyle(CustomStepperStyle())
Example stepper created from custom style properties.

Epoxy Bridging

SwiftUIRow(
title: "Row \(id)",
subtitle: "Subtitle")
.itemModel(dataID: id)
EpoxyRow.swiftUIView(
content: .init(title: "Row \(index)", subtitle: …),
style: .small)
.configure { context in
print("Configuring \(context.view)")
}
.onTapGesture {
print("Row \(index) tapped!")
}

Unidirectional Data Flow

// In Epoxy/UIKit:
struct CounterContentPresenter: StateStoreContentPresenter {
let store: StateStore<CounterState, CounterAction>


var content: UniListViewControllerContent {
.currentDLSStandardStyle()
.items {
BasicRow.itemModel(
dataID: ItemID.count,
content: .init(titleText: "Count \(state.count)"),
style: .standard)
.didSelect { _ in
store.handle(.increment)
}
}
}
}
// In SwiftUI
struct CounterScreen: View {
@ObservedObject
var store: StateStore<CounterState, CounterAction>


var body: some View {
DLSListScreen {
DLSRow(title: "Count \(store.state.count)")
.highlightEffectButton {
store.handle(.increment)
}
}
}
}

Testability

enum DLSPrimaryButton_Definition: ViewDefinition, PreviewProvider {
static var contentVariants: ContentVariants {
DLSPrimaryButton(title: "Title") { … }
.named("Short text")


DLSPrimaryButton(title: "Title") { … }
.disabled(true)
.named("Disabled")
}
}

Education

Findings on SwiftUI

Lines of Code

Performance

Adoption & Developer Satisfaction

The growth of SwiftUI views and screens in Airbnb’s product.

Challenges

Conclusion

--

--

The Airbnb Tech Blog
The Airbnb Tech Blog

Published in The Airbnb Tech Blog

Creative engineers and data scientists building a world where you can belong anywhere. http://airbnb.io

Bryn Bodayle
Bryn Bodayle

Written by Bryn Bodayle

Staff iOS Engineer at Airbnb working on UI tools.

Responses (34)