SwiftUI에서 Combine을 활용한 데이터 필터링: contains와 tryContains 사용법

작성일 :

SwiftUI에서 Combine을 활용한 데이터 필터링: contains와 tryContains 사용법

SwiftUI는 iOS 앱 개발을 위한 강력한 프레임워크로, Combine은 비동기 이벤트 처리 및 반응형 프로그래밍을 지원하는 프레임워크입니다. 이 두 프레임워크를 결합하면 데이터 필터링과 상태 관리를 보다 쉽게 할 수 있습니다. 이번 글에서는 Combine의 containstryContains 연산자를 사용하여 SwiftUI에서 데이터를 필터링하는 방법을 자세히 알아보겠습니다.

1. Combine과 SwiftUI 소개

Combine은 Apple이 제공하는 반응형 프로그래밍 프레임워크로, 비동기 이벤트를 처리하고 데이터를 스트림 형태로 관리할 수 있습니다. Combine은 퍼블리셔(Publisher)와 서브스크라이버(Subscriber) 개념을 기반으로 하며, 다양한 연산자를 제공하여 데이터를 변환하고 필터링할 수 있습니다.

SwiftUI는 선언형 UI 프레임워크로, 상태 기반의 UI 업데이트를 간편하게 할 수 있습니다. Combine과 SwiftUI를 함께 사용하면 데이터 변경에 따라 UI를 자동으로 업데이트할 수 있어 매우 효율적입니다.

2. contains 연산자 사용법

contains 연산자는 퍼블리셔가 특정 요소를 포함하고 있는지 여부를 확인합니다. 예를 들어, 배열 퍼블리셔가 특정 값을 포함하는지 검사할 때 유용합니다.

다음은 contains 연산자를 사용하여 배열에 특정 값이 있는지 확인하는 예제입니다.

swift
import SwiftUI
import Combine

struct ContentView: View {
    @State private var containsValue = false
    @State private var cancellable: AnyCancellable?

    var body: some View {
        VStack {
            Text("Contains value: \(containsValue ? "Yes" : "No")")
                .padding()

            Button("Check Value") {
                checkContainsValue()
            }
        }
    }

    func checkContainsValue() {
        let values = [1, 2, 3, 4, 5].publisher
        cancellable = values
            .contains(3)
            .sink { result in
                containsValue = result
            }
    }
}

이 예제에서는 버튼을 눌러 배열 [1, 2, 3, 4, 5]가 값 3을 포함하는지 확인합니다. contains 연산자는 Bool 값을 반환하며, 결과는 containsValue 상태 변수에 저장됩니다.

3. tryContains 연산자 사용법

tryContains 연산자는 contains와 유사하지만, 오류가 발생할 수 있는 조건을 처리할 수 있습니다. 주로 예외 처리가 필요한 경우 사용됩니다.

다음은 tryContains 연산자를 사용하여 배열에 특정 값이 있는지 확인하는 예제입니다.

swift
import SwiftUI
import Combine

struct ContentView: View {
    @State private var containsValue = false
    @State private var errorMessage: String?
    @State private var cancellable: AnyCancellable?

    var body: some View {
        VStack {
            Text("Contains value: \(containsValue ? "Yes" : "No")")
                .padding()

            if let errorMessage = errorMessage {
                Text("Error: \(errorMessage)")
                    .foregroundColor(.red)
            }

            Button("Check Value with Error Handling") {
                checkContainsValueWithErrorHandling()
            }
        }
    }

    func checkContainsValueWithErrorHandling() {
        let values = [1, 2, 3, 4, 5].publisher
        cancellable = values
            .tryContains { value in
                if value == 4 {
                    throw NSError(domain: "ValueError", code: 100, userInfo: nil)
                }
                return value == 3
            }
            .sink(
                receiveCompletion: { completion in
                    if case .failure(let error) = completion {
                        errorMessage = error.localizedDescription
                    }
                },
                receiveValue: { result in
                    containsValue = result
                }
            )
    }
}

이 예제에서는 배열 [1, 2, 3, 4, 5]의 값 중 3이 있는지 확인하지만, 값 4가 발견되면 오류를 발생시킵니다. 오류가 발생하면 errorMessage 상태 변수에 오류 메시지가 저장됩니다.

4. 실전 예제: 사용자 목록 필터링

이제 Combine의 containstryContains 연산자를 사용하여 사용자 목록을 필터링하는 실전 예제를 살펴보겠습니다. 사용자 목록에서 특정 이름을 포함하는지 확인하는 UI를 만들어 보겠습니다.

swift
import SwiftUI
import Combine

struct User: Identifiable {
    let id: Int
    let name: String
}

struct ContentView: View {
    @State private var userList: [User] = [
        User(id: 1, name: "Alice"),
        User(id: 2, name: "Bob"),
        User(id: 3, name: "Charlie"),
        User(id: 4, name: "David")
    ]
    @State private var searchName: String = ""
    @State private var containsUser: Bool = false
    @State private var cancellable: AnyCancellable?

    var body: some View {
        VStack {
            TextField("Enter name to search", text: $searchName)
                .textFieldStyle(RoundedBorderTextFieldStyle())
                .padding()

            Button("Check User") {
                checkContainsUser()
            }

            Text("Contains user: \(containsUser ? "Yes" : "No")")
                .padding()

            List(userList) { user in
                Text(user.name)
            }
        }
        .padding()
    }

    func checkContainsUser() {
        cancellable = userList.publisher
            .map { $0.name }
            .contains(searchName)
            .sink { result in
                containsUser = result
            }
    }
}

이 예제에서는 TextField를 통해 사용자가 입력한 이름을 searchName 상태 변수에 저장합니다. 버튼을 눌러 searchNameuserList에 있는지 확인합니다. contains 연산자를 사용하여 필터링 결과를 containsUser 상태 변수에 저장합니다.

결론

Combine의 containstryContains 연산자를 사용하면 SwiftUI에서 데이터를 효율적으로 필터링할 수 있습니다. 이 글에서는 배열의 특정 값을 확인하고, 오류를 처리하는 방법을 설명했습니다. 실전 예제를 통해 사용자 목록에서 특정 이름을 검색하는 기능을 구현해 보았습니다. Combine과 SwiftUI를 결합하여 강력하고 반응형 UI를 만들 수 있습니다. 이러한 기법을 활용하면 비동기 데이터 처리와 사용자 인터페이스 업데이트를 보다 간편하게 구현할 수 있습니다.