본문 바로가기
Swift

Swift TCA와 UIKit으로 실시간 검색 앱 만들기

by mr.conan 2023. 7. 25.
728x90
반응형

모델과 액션 정의

TCA의 기본 구성 요소인 상태(State)와 액션(Action)을 정의합니다.

import Foundation

struct AppState: Equatable {
    var searchText: String = ""
    var searchResults: [String] = []
}

enum AppAction {
    case setSearchText(String)
    case setSearchResults([String])
}

 

 

리듀서 정의

앱의 상태(State)와 액션(Action)을 기반으로 리듀서를 정의합니다.

import ComposableArchitecture

let appReducer = Reducer<AppState, AppAction, AppEnvironment> { state, action, environment in
    switch action {
    case let .setSearchText(text):
        state.searchText = text
        return environment.search(text: text)
            .map(AppAction.setSearchResults)

    case let .setSearchResults(results):
        state.searchResults = results
        return .none
    }
}

 

 

화면 구성

UIKit으로 화면을 구성합니다. 이 예제에서는 UIViewController를 사용하여 UI를 구현합니다.

import UIKit
import ComposableArchitecture

class SearchViewController: UIViewController {

    private let searchController = UISearchController(searchResultsController: nil)
    private let tableView = UITableView()
    private var data: [String] = []

    private var cancellables: Set<AnyCancellable> = []
    private let store: Store<AppState, AppAction>

    init(store: Store<AppState, AppAction>) {
        self.store = store
        super.init(nibName: nil, bundle: nil)
    }

    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    override func viewDidLoad() {
        super.viewDidLoad()

        title = "실시간 검색"
        view.backgroundColor = .white

        setupTableView()
        setupSearchController()

        store
            .scope(state: \.searchText, action: AppAction.setSearchText)
            .assign(to: \.searchController.searchBar.text, on: self)
            .store(in: &cancellables)

        store
            .producer
            .map { $0.searchResults }
            .map { results in
                results.map { result in
                    UITableViewCell(style: .default, reuseIdentifier: nil).then {
                        $0.textLabel?.text = result
                    }
                }
            }
            .start(on: DispatchQueue.main)
            .on(value: { [weak self] cells in
                self?.data = cells
                self?.tableView.reloadData()
            })
            .store(in: &cancellables)
    }

    private func setupTableView() {
        view.addSubview(tableView)
        tableView.snp.makeConstraints { make in
            make.edges.equalToSuperview()
        }

        tableView.dataSource = self
        tableView.delegate = self
        tableView.register(UITableViewCell.self, forCellReuseIdentifier: "Cell")
    }

    private func setupSearchController() {
        searchController.searchResultsUpdater = self
        searchController.obscuresBackgroundDuringPresentation = false
        searchController.searchBar.placeholder = "검색어를 입력하세요"
        navigationItem.searchController = searchController
        definesPresentationContext = true
    }
}

extension SearchViewController: UITableViewDataSource, UITableViewDelegate {
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return data.count
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        return data[indexPath.row]
    }
}

extension SearchViewController: UISearchResultsUpdating {
    func updateSearchResults(for searchController: UISearchController) {
        // TCA에서 상태를 처리하므로, 여기에는 추가로 작업이 필요하지 않습니다.
    }
}

 

 

위의 코드를 사용하여 블로그 형식으로 실시간 검색 앱을 구현할 수 있습니다. 이제 실시간으로 검색 결과가 업데이트되는 앱을 만들어볼 수 있습니다. Happy coding! 😊

728x90
반응형