[iOS/Swift] 서치바 사용하여 도서 찾기 어플 구현하기

최정은·2023년 9월 19일
0

Swift

목록 보기
24/27

1. 서치바 사용하기

  • Navigation Controller 추가하기!

  • 서치바 사용했을 때 다른 페이지로 이동하기 위한 뷰 컨트롤러 생성 후 UISearchController 생성하기
let searchController = UISearchController(searchResultsController:  
UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "BookResultViewController") as! BookResultViewController)
  • 네비게이션 아이템에 컨트롤러 적용 및 글자 입력할 때마다 화면에 표시해주기 위해 searchController 프로토콜 채택하기
func setupSearchBar(){
        title = "Book Search"
        
        navigationItem.searchController = searchController
        searchController.searchResultsUpdater = self
        //첫 글자 대문자로 표시안되게 하는 옵션
        searchController.searchBar.autocapitalizationType = .none
    }
  • 유저가 글자를 입력하는 순간마다 호출되는 메서드 추가 및 글자를 치는 순간에 다른 화면에 입력된 글자 전달
extension ViewController: UISearchResultsUpdating{
    func updateSearchResults(for searchController: UISearchController) {
        
        let vc = searchController.searchResultsController as! BookResultViewController
        vc.keyword = searchController.searchBar.text ?? ""
    }
}

2. Nib 파일 사용하여 TableView 구현하기

  • Cell 파일 생성할 때 Also create XIB file 체크하여 생성하기

  • 테이블뷰에 셀 등록하기

 func setupTableView(){
        
        bookTableView.delegate = self
        bookTableView.dataSource = self
        
        // Cell.bookCellIdentifier = Cell 이름
        bookTableView.register(UINib(nibName: Cell.bookCellIdentifier, bundle: nil), forCellReuseIdentifier: Cell.bookCellIdentifier)
    }

3. CollectionView 사용하기

  • View Controller에 컬렉션 뷰 추가하고 셀 내부에 이미지뷰, 레이블 추가

  • 아이템을 한 줄에 3개씩 배치하기 위해, 컬렉션뷰의 레이아웃을 담당하는 객체 생성하기

let flowLayout = UICollectionViewFlowLayout()
  • 프로토콜 채택 및 아이템 사이즈, 간격, 스크롤 방향 설정하기
func setupCollectionView(){
        
        bookCollectionView.dataSource = self
        
        flowLayout.scrollDirection = .vertical
        
        let collectionCellWidth = (UIScreen.main.bounds.width - CVCell.spacingWitdh * (CVCell.cellColumns - 1)) / CVCell.cellColumns
        
        flowLayout.itemSize = CGSize(width: collectionCellWidth, height: collectionCellWidth + 50)
        // 아이템 사이 간격 설정
        flowLayout.minimumInteritemSpacing = CVCell.spacingWitdh
        // 아이템 위아래 사이 간격 설정
        flowLayout.minimumLineSpacing = CVCell.spacingWitdh
        
        // 컬렉션뷰의 속성에 할당
        bookCollectionView.collectionViewLayout = flowLayout
    }

4. 도서 API (도서관 정보나루)

  • 인기도서 정보, 도서 검색, 도서 상세정보 api를 사용하여 기능 구현하기
public enum NetworkError: Error{
    case networkingError
    case dataError
    case parseError
}

public struct NetworkManager{
    // 싱글톤 패턴
    static let shared = NetworkManager()
    private init(){}
    
    typealias NetworkCompletion = (Result<[Book], NetworkError>) -> (Void)
    typealias BookDescriptionNetworkCompletion = (Result<String, NetworkError>) -> (Void)
    
    func fetchBook(completion: @escaping NetworkCompletion) {
        
        let url = "\(BookApi.allBookURL)&\(BookApi.apiKeyParam)&\(BookApi.sizeParam)"
        print(url)
        getBook(url) { result in
            completion(result)
        }
    }
    
    func getBook(_ searchUrl: String, completion: @escaping NetworkCompletion ){
        
        guard let url = URL(string: searchUrl) else { return }
        
        let session = URLSession(configuration: .default)
        session.dataTask(with: url){ (data, response, error) in
            
            if error != nil{
                completion(.failure(.networkingError))
                return
            }
            
            guard let safeData = data else {
                completion(.failure(.dataError))
                return
            }
            
            if let bookData = parseJSON(safeData){
                completion(.success(bookData))
                return
            }
            else
            {
                completion(.failure(.parseError))
                return
            }
        }.resume()
        
    }
    
    func parseJSON(_ bookData: Data) -> [Book]? {
        
        do {
            let bookData = try JSONDecoder().decode(ResponseData.self, from: bookData)
            
            var bookArray: [Book] = []
            
            for item in  bookData.response.docs{
                if let book = item.doc {
                    bookArray.insert(book, at: bookArray.count)
                }
            }
            
            return bookArray
            
        } catch {
            print(error.localizedDescription)
            return nil
        }
    }
    
}

완성!

업로드중..

업로드중..

0개의 댓글