In this tutorial, we’ll walk through creating a transaction list app, explaining key SwiftUI concepts along the way.
Step 1: Setting Up the Data Model
Let’s start by defining our data model. We’ll create a Transaction
struct and an enum for the transaction type.
import SwiftUI struct Transaction: Identifiable { let id: UUID let date: Date let amount: Double let description: String let type: TransactionType } enum TransactionType { case credit case debit }
Key points:
Transaction
conforms toIdentifiable
, which is required for use in SwiftUI Lists.- We use an enum for
TransactionType
to ensure type safety.
Step 2: Creating the Main View
Now, let’s create our main view, TransactionListView
:
struct TransactionListView: View { @State private var transactions: [Transaction] = [] var body: some View { NavigationView { VStack { List(transactions) { transaction in NavigationLink(destination: TransactionDetailView(transaction: transaction)) { TransactionRowView(transaction: transaction) } } .navigationTitle("Transactions") } .onAppear { loadTransactions() } .refreshable { loadTransactions() } } } private func loadTransactions() { // Simulated API call DispatchQueue.main.asyncAfter(deadline: .now() + 1) { // Populate transactions array } } }
Key components:
@State
: This property wrapper is used for thetransactions
array. It tells SwiftUI to update the view when this value changes.NavigationView
: Provides a navigation container for our list.List
: Efficiently displays our transactions.NavigationLink
: Enables navigation to a detail view for each transaction..onAppear
: Loads transactions when the view appears..refreshable
: Adds pull-to-refresh functionality.
Step 3: Creating a Row View
The TransactionRowView
represents each row in our list:
struct TransactionRowView: View { let transaction: Transaction var body: some View { HStack { VStack(alignment: .leading) { Text(transaction.description) .font(.headline) Text(transaction.date, style: .date) .font(.subheadline) .foregroundColor(.secondary) } Spacer() Text(String(format: "$%.2f", transaction.amount)) .foregroundColor(transaction.type == .credit ? .green : .red) } } }
Key points:
HStack
andVStack
are used for horizontal and vertical layouts.- We use different text styles and colors to distinguish between elements.
- The amount color changes based on the transaction type.
Step 4: Creating a Detail View
The TransactionDetailView
shows more information about a selected transaction:
struct TransactionDetailView: View { let transaction: Transaction var body: some View { VStack(alignment: .leading, spacing: 20) { Text(transaction.description) .font(.title) Text(transaction.date, style: .date) Text(String(format: "$%.2f", transaction.amount)) .font(.title2) .foregroundColor(transaction.type == .credit ? .green : .red) Text("Type: \(transaction.type == .credit ? "Credit" : "Debit")") Spacer() } .padding() .navigationTitle("Transaction Details") } }
Key points:
- We use
VStack
for vertical layout with custom spacing. - Different font sizes and colors are used to highlight important information.
.navigationTitle
sets the title for this view when navigated to.
Step 5: Implementing Data Loading
In a real app, you’d fetch data from an API or database. Here’s a simulated data loading function:
private func loadTransactions() { // Simulate API call DispatchQueue.main.asyncAfter(deadline: .now() + 1) { self.transactions = [ Transaction(id: UUID(), date: Date().addingTimeInterval(-86400 * 2), amount: 120.50, description: "Grocery Shopping", type: .debit), Transaction(id: UUID(), date: Date().addingTimeInterval(-86400), amount: 1500.00, description: "Salary Deposit", type: .credit), // Add more transactions... ] } }
Key points:
- We use
DispatchQueue.main.asyncAfter
to simulate an asynchronous API call. - In a real app, you’d replace this with actual networking code.
Conclusion
This tutorial covered several key SwiftUI concepts:
- Creating and using custom data models
- Building list views with
NavigationView
andList
- Implementing navigation with
NavigationLink
- Creating reusable subviews
- Using
@State
for managing view state - Implementing pull-to-refresh functionality
By understanding these components, you’re well on your way to building more complex SwiftUI applications.