List in SwiftUI with RxSwift

FARAZ ZAFAR
3 min readJun 27, 2024

--

SwiftUI, Apple’s declarative framework for building user interfaces, pairs exceptionally well with RxSwift, a powerful framework for reactive programming. Together, they enable developers to create dynamic and responsive UIs effortlessly. In this article, we’ll build a simple SwiftUI app that demonstrates the integration of RxSwift for handling asynchronous data streams.

Prerequisites

Before we start, ensure you have the following:

  • Xcode 11 or later
  • Basic understanding of Swift, SwiftUI, and RxSwift

Setting Up the Project

Step 1: Create a New Project

  1. Open Xcode and create a new “Single View App” project.
  2. Name your project and ensure the language is set to Swift.
  3. Choose SwiftUI as the user interface.

Step 2: Install RxSwift and RxCocoa

  1. Close Xcode.
  2. Open Terminal and navigate to your project directory.
  3. Run pod init to create a Podfile.
  4. Open the Podfile and add the following lines:
target 'YourProjectName' do
use_frameworks!

pod 'RxSwift'
pod 'RxCocoa'
end

5. Install the pods by running pod install.

6. Open the generated .xcworkspace file to continue working on your project in Xcode.

Building the SwiftUI View

Step 1: Create the ViewModel

First, create a ViewModel that will handle the business logic using RxSwift.

import Foundation
import RxSwift
import RxCocoa

class CitySearchViewModel: ObservableObject {
@Published var searchText: String = ""
@Published var filteredCities: [String] = []

private let disposeBag = DisposeBag()
private let cities = ["New York", "Los Angeles", "Chicago", "Houston", "Phoenix", "Philadelphia", "San Antonio", "San Diego", "Dallas", "San Jose"]

init() {
setupBindings()
}

private func setupBindings() {
$searchText
.debounce(for: .milliseconds(300), scheduler: RunLoop.main)
.removeDuplicates()
.map { [unowned self] query in
self.cities.filter { $0.lowercased().contains(query.lowercased()) }
}
.assign(to: &$filteredCities)
}
}

Step 2: Create the SwiftUI View

Now, create the SwiftUI view that will interact with the ViewModel.

import SwiftUI

struct CitySearchView: View {
@StateObject private var viewModel = CitySearchViewModel()

var body: some View {
NavigationView {
VStack {
TextField("Search", text: $viewModel.searchText)
.textFieldStyle(RoundedBorderTextFieldStyle())
.padding()

List(viewModel.filteredCities, id: \.self) { city in
NavigationLink(destination: Text(city)) {
Text(city)
}
}
}
.navigationTitle("City Search")
}
}
}

struct CitySearchView_Previews: PreviewProvider {
static var previews: some View {
CitySearchView()
}
}

Explanation

  1. ViewModel Setup: The CitySearchViewModel class uses @Published properties to automatically update the UI when searchText or filteredCities changes. The setupBindings method sets up the binding for searchText, debouncing the input to reduce unnecessary filtering and using removeDuplicates to avoid redundant updates. The filtered results are then assigned to the filteredCities property.
  2. SwiftUI View: The CitySearchView struct defines the UI. It contains a TextField for input and a List to display the filtered cities. The @StateObject attribute ensures that the view updates whenever the ViewModel's properties change.

Running the App

Build and run the app on the simulator or a physical device. You should see a text field at the top of the screen. As you type into the text field, the list below should update in real-time, showing cities that match the search query.

Conclusion

This article demonstrates how to integrate RxSwift with SwiftUI to build a dynamic, reactive user interface. By combining the power of RxSwift for handling asynchronous data streams and SwiftUI for declarative UI development, you can create highly responsive and maintainable applications. In order to learn Basic SwiftUI design creation follow these links: SimpleSwiftUI, LoginScreenSwiftUI.

Github

https://github.com/faraz-zafar/List_SwiftUI_RxSwift

--

--