본문 바로가기
Project/SwiftUI 블록와이드

[SwiftUI Project] 검색화면 전환 개선하기 GeometryReader

by iOS_woo 2022. 9. 15.

NavigationLink로 전환을 했을 때 새롭게 데이터가 로드되니 불편하다.

홈화면에서 검색화면으로 전환 시 문제라고 생각되는 부분이 생겼습니다.

전환이 되었을 때 코인 리스트가 바로 보여졌으면 좋겠는데.. gif에서 보이는 것처럼 몇 초 느리게 보여졌는데요.  

홈화면에서 이미 한번 호출했던 데이터인데 어째서 이렇게 느릴까요?

아무래도 제 생각에는 검색화면에서 호출될 때 데이터를 받아오는 작업이 다시 일어나는 것이 아닐까 싶습니다.

 

검색기능은 앱에서 유저가 자주 사용하는 기능입니다. 

검색화면으로 전환했을 때 미리 데이터가 준비되어있다가 로드된다면 좋을 것 같습니다. 

 

그래서 찾은 방법은 GeomeryReader를 사용해서 SearchView를 옆에서 등장시키는 것입니다. 

HomeView와 함께 데이터를 로드하고 사용자가 버튼을 눌렀을 때 즉시 옆에서 등장하는 방식입니다. 

 

GeomeryReader를 사용해 개선된 사용자 경험

 

사용자 경험은 확실히 좋아진 것 같습니다. 

만약 큰 데이터가 로드되어야 한다면 무리가 될 수도 있을 것 같은데요. 

그렇지 않고 이미 호출되었던 데이터 혹은 가벼운 데이터라면 괜찮은 방법이 아닐까 싶습니다.

 

 

HomeView.Swift

import SwiftUI

struct HomeView: View {
    
    @EnvironmentObject private var viewModel: HomeViewModel
    @State private var showMenu: Bool = false
    @State private var showSearchView: Bool = false <- 화면 전환을 위한 상태프로퍼티
    
    var body: some View {
        ZStack {
            // Background layer
            Color.theme.background
                .ignoresSafeArea()
            
            // content layer
            VStack(spacing: 0) {
                homeHeader
                listOptionBar
                sortOptionList
                AllCoinListView(viewModel: viewModel)
                Spacer(minLength: 0)
            }
            searchView
        }
    }
}

extension HomeView {
    private var homeHeader: some View {
        HStack {
            IconView(iconName: showMenu ? "arrow.left" : "person.circle")
                .onTapGesture {
                    withAnimation() {
                        showMenu.toggle()
                    }
                }
                .animation(.none, value: showMenu)
            
            Spacer()
            
            if !showMenu {
                HStack {
                    IconView(iconName: "magnifyingglass")
                        .padding(.trailing, -20)
                        .onTapGesture {
                            withAnimation { <- 화면 전환에 애니메이션을 추가합니다.
                                showSearchView.toggle() <- showSearchView의 Bool값을 변경합니다.
                            }
                        }
                    IconView(iconName: "qrcode.viewfinder")
                }
            } else {
                IconView(iconName: "sun.min.fill")
                    .padding(.trailing, 18)
            }
        }
    }
    
    private var searchView: some View {
        GeometryReader {_ in
            SearchView(showSearchView: $showSearchView) <- $로 상태프로퍼티와 바인딩 
                .offset(x: showSearchView ? 0 : UIScreen.main.bounds.width) <- 화면 전환
                .animation(.easeInOut(duration: 0.2), value: showSearchView) <- 애니메이션 속도
        }
    }
}

 

SearchView.Swift

import SwiftUI

struct SearchView: View {
    
    @StateObject private var viewModel = HomeViewModel()
    @Binding var showSearchView: Bool <- HomeView의 상태프로퍼티와의 바인딩
    
    var body: some View {
        ZStack {
            Color.theme.background
                .ignoresSafeArea()
            VStack(spacing: 0) {
                searchBar
                listOptionBar
                AllCoinListView(viewModel: viewModel)
                    .padding(.top, 10)
                Spacer(minLength: 0)
            }
        }
        .navigationBarHidden(true)
    }
}

extension SearchView {
    
    private var searchBar: some View {
        HStack {
            SearchBarView(searchText: $viewModel.searchText)
                .frame(width: 320)
            Spacer()
            Text("Cancel")
                .foregroundColor(Color.theme.binanceColor)
                .font(.subheadline)
                .onTapGesture {
                    withAnimation {
                        showSearchView.toggle() <- HomeView의 상태프로퍼티를 업데이트합니다.
                    }
                }
        }
        .padding()
    }
}

 

@State, @Binding 블로그: 

 

[SwiftUI] state property 정리 (@state, @Binding)

요약 뷰 내부에서 특정 View 의 상태를 나타내는 변수 뷰내부에서 밖에 사용이 불가능함 때문에 private로 선언 하위 뷰나 다른 뷰에서 참조하기 위해선 @Binding 해야함 state property에 해당하는 변수

huniroom.tistory.com

Create a SideMenu 유튜브: 

 

글 작성 며칠 후의 코멘트 : 

GeometryReager를 활용한 화면전환을 할 때 자잘한 버그가 많아서 다시 NavigationLink로 돌아갔습니다..! 

first Responder, 키보드 애니메이션 등에서 불편한 움직임들이 있었습니다. 

 

이 글의 내용은 복잡한 기능을 가진 뷰를 보여줄 때보다는 단순히 텍스트로 이뤄진 사이드메뉴를 다루는게 적합하다고 생각되었습니다. :)

댓글