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

[블록와이드] 뉴스 검색 기능 추가, 보완하고 싶은 점

by iOS_woo 2023. 2. 14.

추가된 검색 기능

뉴스를 검색할 수 있는 화면을 추가했습니다. 
매우 멋진 기능이에요!😄

이번 작업에서의 핵심은 FirstResponderTextField를 다루는 것이었습니다. 

* FirstResponderTextField: 텍스트필드가 보여지면 자동으로 포커싱되는 기능을 가진 텍스트필드

SwiftUI로 iOS 14에 FirstResponderTextField를 구현하려면 다음과 같이 긴 코드를 생성해줘야 합니다. 

(제가 쓰고 있는 코드라서 불필요한 변수들이 있습니다!)

struct FirstResponderTextField: UIViewRepresentable {
    
    class Coordinator: NSObject, UITextFieldDelegate {
        
        @Binding var searchText: String
        @Binding var didReturn: Bool
        var becameFirstResponder = false
        
        init(searchText: Binding<String>, didReturn: Binding<Bool>) {
            self._searchText = searchText
            self._didReturn = didReturn
        }
        
        func textFieldDidChangeSelection(_ textField: UITextField) {
            searchText = textField.text ?? ""
            textField.text = String(searchText.prefix(15)) // 글자 수 제한
        }
        
        // 리턴키를 누르면 포커스 해제됩니다.
        // 리턴키를 누르면 didReturn이 토글됩니다.
        func textFieldShouldReturn(_ textField: UITextField) -> Bool {
            didReturn.toggle()
            textField.resignFirstResponder()
            return true
        }
    }
    
    @Binding var searchText: String
    @Binding var didReturn: Bool
    let placeHolder: String
    
    func makeUIView(context: Context) -> some UIView {
        let textField = UITextField()
        textField.delegate = context.coordinator
        textField.placeholder = placeHolder
        return textField
    }
    
    func makeCoordinator() -> Coordinator {
        return Coordinator(searchText: $searchText, didReturn: $didReturn)
    }
    
    func updateUIView(_ uiView: UIViewType, context: Context) {
        if !context.coordinator.becameFirstResponder {
            uiView.becomeFirstResponder()
            context.coordinator.becameFirstResponder = true
        }
    }
}

프로젝트에서 사용했지만, return 버튼이 눌릴 때 액션을 발생시키는 등의 작업은 어떻게 하는지 잘 알지 못했습니다. 

이번에 검색 기능을 구현하면서 텍스트 필드의 동작 여부를 파악해야 했고, 덕분에 좋은 공부가 되었습니다.

 

화면을 구성하는 코드는 다음과 같습니다. 

struct HeadlineSearchView: View {
    
    @Environment(\.presentationMode) var presentationMode
    @State private var searchText = ""
    @State private var keyword = ""
    @State private var didReturn = false
    @State private var refreshList = false
    
    var body: some View {
        VStack(spacing: 0) {
            searchBar
            Divider()
            if keyword.isEmpty {
                Spacer()
            } else {
                if refreshList {
                    HeadlineListView(keyword: keyword)
                } else {
                    HeadlineListView(keyword: keyword)
                }
            }
        }
        .background(Color.theme.background.ignoresSafeArea())
        .navigationBarHidden(true)
	// 키보드에서 return을 누르면 didReturn이 토글됩니다. 
        // onChange를 통해 didReturn이 변하면 keyword에 값을 바꿔주고 리스트를 새로고침해줍니다!
        .onChange(of: didReturn) { _ in
            keyword = searchText
            refreshList.toggle()
        }
    }
}

private extension HeadlineSearchView {
    var searchBar: some View {
        HStack {
            SearchBarView(searchText: $searchText, didReturn: $didReturn)
            Spacer()
            Text("취소")
                .foregroundColor(Color.theme.textColor)
                .font(.subheadline)
                .padding(.leading, 5)
                .onTapGesture {
                    UIApplication.shared.endEditing()
                    presentationMode.wrappedValue.dismiss()
                    self.searchText = ""
                }
        }
        .frame(maxWidth: UIScreen.main.bounds.width)
        .padding()
        .padding(.bottom, -8)
    }
}

 

지금의 검색 화면에서 조금 더 사용성이 좋게 발전시키고 싶은데..  다음과 같이 개선하면 어떨까 싶어요. 

멋진 유튜브의 검색 기능!

유튜브 앱의 검색기능을 관찰해보면 텍스트 필드의 포커싱 여부에 따라서 뷰가 변하는 것을 알 수 있습니다. 

이에 따라서 저도 isFocus: Bool 변수를 만들어서 조금 더 사용성이 좋은 화면을 만들어 보겠습니다!

 

디자인 실력이 없으니.. 좋은 앱의 사용자경험을 모방하는 것이 현재로썬 최선인 것 같아요.. 하하  😅😀😀🥲

홧팅! 

댓글