본문 바로가기

프로젝트/Twitter Clone App (w∕Firebase)

17. 기능 구현 #5

기능 구현 #5
유저 검색 기능


유저 검색 기능
| SearchBar

 

29. List의 부가 기능 구현하기

List의 부가 기능 구현하기 Pull Refresh Apple Developer Documentation developer.apple.com 화면을 아래로 끌어당겨 새로고침 하는 iOS의 가장 보편적인 새로고침 방식이다. struct PullToRefresh: View { @State private var ite

chillog.page

SwiftUI에서도 SearchBar를 제공하지만 List나 NavigationView 등 특정 View만 지원하므로
심미적인 목적이나 구현 스타일에 따라 새롭게 구성할 수 있어야 한다.

struct SearchBar: View {
    @Binding var text: String
}

SearchBar는 사용자에게서 검색어를 입력 받고, 이를 ExploreView에서 사용할 수 있어야 한다.
따라서 상위 View에서 선언한 변수를 사용할 수 있도록 Binding으로 변수를 하나 선언한다.

struct SearchBar: View {
    @Binding var text: String

    var body: some View {
        TextField("Search...", text: $text)
                .padding(8)
                .padding(.horizontal, 24)
                .background(Color(.systemGray6))
                .cornerRadius(8)
                .padding(.horizontal, 4)
    }
}

사용자가 검색어를 입력할 수 있도록 TextField를 하나 구성했다.

struct SearchBar: View {
    @Binding var text: String

    var body: some View {
        TextField("Search...", text: $text)
            .padding(8)
            .padding(.horizontal, 24)
            .background(Color(.systemGray6))
            .cornerRadius(8)
            .overlay {
                    Image(systemName: "magnifyingglass")
                        .foregroundColor(.gray)
                        .frame(minWidth: 0, maxWidth: .infinity, alignment: .leading)
                        .padding(.leading, 8)
            }
            .padding(.horizontal, 4)
    }
}

검색창임을 확실히 할 수 있도록 overlay를 사용해 돋보기 아이콘을 표시했다.

유저 검색 기능
| ExploreView

struct ExploreView: View {
    @ObservedObject var viewModel = ExploreViewModel()
    @State private var searchText = ""

    var body: some View {
        VStack {
            SearchBar(text: $searchText)
                .padding()

            ScrollView {
                LazyVStack {
                    ForEach(viewModel.users) { user in
                        NavigationLink {
                            ProfileView(user: user)
                        } label: {
                            UserRowView(user: user)
                        }

                    }
                }
            }
        }
        .navigationTitle("Explore")
        .navigationBarTitleDisplayMode(.inline)
    }
}

SearchBar에 Binding으로 전달할 State 변수를 하나 선언하고,
ScrollView 위에 표시되도록 SearchBar를 배치한다.

이렇게 ExploreView의 상단에 SearchBar가 생겼다.

유저 검색 기능
| ExploreViewModel

class ExploreViewModel: ObservableObject {
    @Published var users = [User]()
    @Published var searchText = ""

    var searchableUsers: [User] {
        if searchText.isEmpty {
            return users

본격적으로 검색 기능을 구현하기 위해 검색어를 받아 올 속성을 하나 선언한다.
Published 변수인 searchText는 이후 SearchBar에 Binding으로 전달 될 변수이다.

var searchableUsers: [User] {
    if searchText.isEmpty {
        return users
    } else {
    
    }
}

만약 searchText가 비어있다면 전체 사용자 목록을 표시할 수 있도록 전체 사용자 배열인 users를 반환한다.

var searchableUsers: [User] {
    if searchText.isEmpty {
        return users
    } else {
        let lowercasedQuery = searchText.lowercased()

        return users.filter({
            $0.username.contains(lowercasedQuery) || $0.fullname.lowercased().contains(lowercasedQuery)
        })
    }
}

검색어가 존재한다면 검색어를 소문자로 변환한 뒤, 전체 사용자 배열인 users 배열을 검색어로 필터링해, 이를 반환한다.
이렇게 반환되는 배열의 이름은 searchableUsers 이다.

유저 검색 기능
| ExploreView

struct ExploreView: View {
    @ObservedObject var viewModel = ExploreViewModel()

    var body: some View {
        VStack {
            SearchBar(text: $viewModel.searchText)
                .padding()

            ScrollView {
                LazyVStack {
                    ForEach(viewModel.searchableUsers) { user in
                        NavigationLink {
                            ProfileView(user: user)
                        } label: {
                            UserRowView(user: user)
                        }

                    }
                }
            }
        }
        .navigationTitle("Explore")
        .navigationBarTitleDisplayMode(.inline)
    }
}

ExploreViewModel에 검색 기능을 위한 Published 변수 searchText가 생겼으므로 ExploreView의 임시 변수는 삭제했다.

SearchBar(text: $viewModel.searchText)
    .padding()

SearchBar의 파라미터로 viewModel의 searchText를 Binding으로 전달하고,

ForEach(viewModel.searchableUsers) { user in
    NavigationLink {
        ProfileView(user: user)
    } label: {
        UserRowView(user: user)
    }
}

표시할 사용자의 목록은 searchableUsers로 변경한다.

동작하는 모습은 위와 같다.

'프로젝트 > Twitter Clone App (w∕Firebase)' 카테고리의 다른 글

19. 기능 구현 #7  (0) 2023.01.14
18. 기능 구현 #6  (0) 2023.01.13
16. 코드 가독성 개선  (0) 2023.01.11
15. 기능구현 #4  (0) 2023.01.11
14. 버그 수정 #1  (0) 2023.01.11