Skip to content

Latest commit

ย 

History

History
143 lines (112 loc) ยท 5.3 KB

220222_UISearchController.md

File metadata and controls

143 lines (112 loc) ยท 5.3 KB

220222 UISearchController

TIL (Today I Learned)

2์›” 22์ผ (ํ™”)

ํ•™์Šต ๋‚ด์šฉ

  • UISearchController

ย 

๊ณ ๋ฏผํ•œ ์  / ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•

[UISearchController]

https://developer.apple.com/documentation/uikit/uisearchcontroller

๋ฉ”๋ชจ์žฅ ์•ฑ์˜ ๊ฒ€์ƒ‰ํ•˜๋Š” ๊ธฐ๋Šฅ์€ ์–ด๋–ป๊ฒŒ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ์„๊นŒ?

Navigation Item์—๋Š” searchController๋ผ๋Š” ํ”„๋กœํผํ‹ฐ๊ฐ€ ์กด์žฌํ•œ๋‹ค. ์—ฌ๊ธฐ์— UISearchController๋ฅผ ์ƒ์„ฑํ•˜์—ฌ ํ• ๋‹นํ•ด์ค€๋‹ค.

let searchController = UISearchController(searchResultsController: nil) // ๊ฒ€์ƒ‰ ์ปจํŠธ๋กค๋Ÿฌ ์ƒ์„ฑ
searchController.searchBar.placeholder = "Search" // placeholder ํ• ๋‹น
searchController.hidesNavigationBarDuringPresentation = false // ์Šคํฌ๋กค์‹œ ๋„ค๋น„๊ฒŒ์ด์…˜ ๋ฐ”๋ฅผ ์ˆจ๊ธธ๊ฑด์ง€ ์—ฌ๋ถ€
searchController.searchResultsUpdater = self // delegate
searchController.searchBar.delegate = self // delegate
searchController.searchBar.setShowsCancelButton(false, animated: false) // ๊ฒ€์ƒ‰๋ฐ”์˜ cancel ๋ฒ„ํŠผ์„ ๋ณด์—ฌ์ค„์ง€ ์—ฌ๋ถ€

navigationItem.searchController = searchController // ๋„ค๋น„๊ฒŒ์ด์…˜ ์•„์ดํ…œ ํ• ๋‹น
navigationItem.hidesSearchBarWhenScrolling = true // ์Šคํฌ๋กค์‹œ ๊ฒ€์ƒ‰๋ฐ”๋ฅผ ์ˆจ๊ธธ๊ฑด์ง€ ์—ฌ๋ถ€

์ถ”๊ฐ€๋œ ๊ฒ€์ƒ‰๋ฐ”

  • ์Šคํฌ๋กค์„ ๋‚ด๋ ธ์„ ๋•Œ ๋‚˜ํƒ€๋‚˜๋Š” ๊ฒ€์ƒ‰๋ฐ”

๊ฒ€์ƒ‰ํ•  ๋•Œ๋งˆ๋‹ค ํ•ด๋‹น ๊ฒ€์ƒ‰์–ด๊ฐ€ ํฌํ•จ๋˜์–ด์žˆ๋Š” ๋ฉ”๋ชจ๋ฅผ ๋ถˆ๋Ÿฌ์™€์„œ ๋ณด์—ฌ์ฃผ๊ณ  ์‹ถ๋‹ค!

  • ์ง„ํ–‰ํ•˜๊ณ  ์žˆ๋˜ ํ”„๋กœ์ ํŠธ๋Š” ์ฝ”์–ด๋ฐ์ดํ„ฐ๋ฅผ ํ™œ์šฉํ•˜์—ฌ ๋ฉ”๋ชจ๋ฅผ ์ €์žฅํ•˜๊ณ  ์žˆ๋Š” ํ˜•ํƒœ์˜€๋‹ค.
    • NSPredicate๋ฅผ ํ™œ์šฉํ•˜์—ฌ ํ•„ํ„ฐ๋งํ•˜์—ฌ fetch๋ฅผ ์ง„ํ–‰ํ•œ๋‹ค.
    • ๊ทธ๋ฆฌ๊ณ  tableView๋ฅผ reloadํ•ด์ค€๋‹ค.
final class PersistentManager {
private(set) var notes = [Note]() // ๋ทฐ์— ๋ณด์—ฌ์ค„ ๋ฐ์ดํ„ฐ๋ฅผ ๋‹ด์•„๋‘๋Š” ๋ฐฐ์—ด
...
@discardableResult
    func fetch( // ์ €์žฅ๋œ ์ฝ”์–ด๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ค๋Š” ๋ฉ”์†Œ๋“œ
        entityName: String = "Note",
        predicate: NSPredicate? = nil,
        sortDescriptors: [NSSortDescriptor]? = [NSSortDescriptor(key: "lastModified", ascending: false)]
    ) -> [Note]? {
        let context = persistentContainer.viewContext
        let request = NSFetchRequest<NSManagedObject>(entityName: entityName)
        request.predicate = predicate
        request.returnsObjectsAsFaults = false
        request.sortDescriptors = sortDescriptors
        guard let newData = try? context.fetch(request) as? [Note] else {
            return nil
        }
        return newData
    }
...

func setUpNotes() { // fetch๋ฅผ ํ™œ์šฉํ•˜์—ฌ notes๋ฅผ ์„ค์ •ํ•˜๋Š” ๋ฉ”์†Œ๋“œ
        guard let newData = fetch() else {
            return
        }
        self.notes = newData
    }
...

๋‚ด ๊ฒฝ์šฐ์—๋Š” ์ฝ”์–ด๋ฐ์ดํ„ฐ๋ฅผ ๊ด€๋ฆฌํ•˜๋Š” ํƒ€์ž… ๋‚ด๋ถ€์—์„œ tableView์— ๋ณด์—ฌ์งˆ ๋ฐ์ดํ„ฐ๋„ ๊ฐ™์ด ๊ด€๋ฆฌํ•˜๊ธฐ ๋•Œ๋ฌธ์—, fetch๋ฅผ ๋ฐ›์•„์˜จ ๋‹ค์Œ ๋ฐฐ์—ด์— ํ• ๋‹นํ•ด์ฃผ๋Š” ๊ธฐ๋Šฅ์„ ์ถ”๊ฐ€ํ•˜์—ฌ ์ง„ํ–‰ํ•ด์ฃผ์—ˆ๋‹ค.

final class PersistentManager {
private(set) var notes = [Note]()
...
    func searchNote(text: String) {
        guard let searchData = fetch(
            predicate: NSPredicate(format: "body CONTAINS[c] %@", text) // body์— text๊ฐ€ ํฌํ•จ๋˜์–ด์žˆ๋Š” ๊ฒƒ๋“ค์„ ํ•„ํ„ฐ๋ง
        ) else {
            return
        }
        self.notes = searchData
    }
...
  • ๋”ฐ๋ผ์„œ ์œ„์™€ ๊ฐ™์€ searchNote(text:) ๋ผ๋Š” ๋ฉ”์†Œ๋“œ๋ฅผ ๊ตฌํ˜„ํ•ด์ฃผ์—ˆ๋‹ค.
extension NotesViewController: UISearchResultsUpdating {
    func updateSearchResults(for searchController: UISearchController) {
        guard let searchText = searchController.searchBar.text, searchText != "" else { // ๊ฒ€์ƒ‰์–ด๊ฐ€ ๋น„์–ด์žˆ๋‹ค๋ฉด return
            return
        }
        PersistentManager.shared.searchNote(text: searchText)
        tableView.reloadData()
    }
}
  • ๊ทธ๋ฆฌ๊ณ  UISearchResultsUpdating๋ฅผ ์ฑ„ํƒํ•˜์—ฌ updateSearchResults(for:) ๋ฉ”์†Œ๋“œ๋ฅผ ๊ตฌํ˜„ํ•˜์—ฌ ์œ„์—์„œ ๋งŒ๋“ค์—ˆ๋˜ searchNote ๋ฉ”์†Œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜๊ณ  ํ…Œ์ด๋ธ”๋ทฐ๋ฅผ reload ์‹œ์ผœ์ฃผ์—ˆ๋‹ค.

๊ฒ€์ƒ‰์–ด๊ฐ€ ์—†๋Š” ๊ฒฝ์šฐ์—๋Š” ๋ฉ”๋ชจ์˜ ์ „์ฒด๋ฅผ ๋‹ค์‹œ ๊ฐ€์ ธ์˜ฌ ์ˆœ ์—†์„๊นŒ...?

  • ๊ฒ€์ƒ‰์–ด๋ฅผ ์ง€์›Œ๋„ ์•„๊นŒ ๊ฒ€์ƒ‰ํ–ˆ๋˜ ๋ฉ”๋ชจ๋งŒ ๋‚จ์•„์žˆ๋‹ค.
  • ์ฆ‰, ๋‹ค์‹œ ๋ฉ”๋ชจ์˜ ์ „์ฒด ๋ชฉ๋ก์„ ๋ณด๋ ค๋ฉด ์•ฑ์„ ๊ป๋‹ค ์ผœ์•ผํ•˜๋Š”... ํ˜„์ƒ์ด ๋‚˜ํƒ€๋‚œ ๊ฒƒ์ด๋‹ค.

  • ๋”ฐ๋ผ์„œ UISearchBarDelegate๋ฅผ ํ™œ์šฉํ•ด์„œ ์•„๋ž˜์™€ ๊ฐ™์ด ๊ตฌํ˜„ํ•ด์ฃผ์—ˆ๋‹ค.
extension NotesViewController: UISearchBarDelegate {
    func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
        guard searchBar.text == "" else { // ๊ฒ€์ƒ‰์–ด๊ฐ€ ๋น„์–ด์žˆ์ง€ ์•Š๋‹ค๋ฉด return
            return
        }
        PersistentManager.shared.setUpNotes() // ๊ฒ€์ƒ‰์–ด๊ฐ€ ๋น„์–ด์žˆ๋‹ค๋ฉด ๋‹ค์‹œ notes๋ฅผ ์„ค์ •ํ•˜๋Š” ๋ฉ”์†Œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜๊ณ 
        tableView.reloadData() // tableView๋ฅผ reloadํ•œ๋‹ค.
    }
}
  • ์œ„ ๋ฉ”์†Œ๋“œ๋Š” ํ…์ŠคํŠธ๊ฐ€ ๋ณ€๊ฒฝ๋  ๋•Œ๋งˆ๋‹ค ํ˜ธ์ถœ๋˜๋Š” ๋ฉ”์†Œ๋“œ์ด๋‹ค.

๊ฒ€์ƒ‰์–ด๊ฐ€ ์กด์žฌํ•˜์ง€ ์•Š๋‹ค๋ฉด ์ „์ฒด๋ชฉ๋ก์„ ๋ณด์—ฌ์ฃผ๋Š” ๋ชจ์Šต