Storyboard에서 TableView와 SearchBar를 아래 사진과 같이 생성해주세요.
tableview에 datasoruce와 delegate 설정해주시고 searchbar에도 delegate를 설정해주세요.
tableviewcell은 이런식으로 설정해주었습니다.
class Cell: UITableViewCell{
@IBOutlet weak var titleLabel: UILabel!
@IBOutlet weak var subtitleLabel: UILabel!
}
우선 MapKit을 import 해준 후 tableView와 searchbar를 IBOutlet으로 연결해주었습니다.
import UIKit
import MapKit
class ViewController: UIViewController {
@IBOutlet weak var tableView: UITableView!
@IBOutlet weak var searchbar: UISearchBar!
private var searchCompleter: MKLocalSearchCompleter?
private var searchRegion: MKCoordinateRegion = MKCoordinateRegion(MKMapRect.world)
var completerResults: [MKLocalSearchCompletion]?
private var places: MKMapItem? {
didSet {
tableView.reloadData()
}
}
private var localSearch: MKLocalSearch? {
willSet {
// Clear the results and cancel the currently running local search before starting a new search.
places = nil
localSearch?.cancel()
}
}
resultType은 검색할 유형을 나타냅니다.
region은 검색할 지역 범위를 나타냅니다.
Completer 개체는 수명이 긴 개체이므로 강력한 참조를 하기 때문에viewDidDisappear에서 참조를 해제 해줍니다.
override func viewDidLoad() {
super.viewDidLoad()
searchCompleter = MKLocalSearchCompleter()
searchCompleter?.delegate = self
searchCompleter?.resultTypes = .address // 혹시 값이 안날아온다면 이건 주석처리 해주세요
searchCompleter?.region = searchRegion
searchbar.delegate = self
tableView.dataSource = self
tableView.delegate = self
}
override func viewDidDisappear(_ animated: Bool) {
super.viewDidDisappear(animated)
searchCompleter = nil
}
searchCompleter?.queryFragment에 SearchBar에 입력된 값을 넘겨줍니다.
extension ViewController: UISearchBarDelegate {
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
if searchText == "" {
completerResults = nil
}
searchCompleter?.queryFragment = searchText
}
}
searchCompleter?.queryFragment에 들어온 값을 토대로 Location을 검색합니다.
func completerDidUpdateResults(_ completer: MKLocalSearchCompleter)에 completer.results를 통해 검색한 결과를 completerResults에 담습니다.
func completer(_ completer: MKLocalSearchCompleter, didFailWithError error: Error)를 통해 에러를 확인합니다.
extension ViewController: MKLocalSearchCompleterDelegate {
func completerDidUpdateResults(_ completer: MKLocalSearchCompleter) {
completerResults = completer.results
tableView.reloadData()
}
func completer(_ completer: MKLocalSearchCompleter, didFailWithError error: Error) {
if let error = error as NSError? {
print("MKLocalSearchCompleter encountered an error: \(error.localizedDescription). The query fragment is: \"\(completer.queryFragment)\"")
}
}
}
completerResult의 값을 tableView에 나타냅니다.
title은 관심 지점과 관련된 제목 문자열입니다.
subtitle은 관심 지점과 관련된 부제목 (있는 경우)입니다.
extension ViewController: UITableViewDataSource{
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return completerResults?.count ?? 0
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let cell = tableView.dequeueReusableCell(withIdentifier: "Cell") as? Cell else { return UITableViewCell()}
if let suggestion = completerResults?[indexPath.row] {
cell.titleLabel.text = suggestion.title
cell.subtitleLabel.text = suggestion.subtitle
}
return cell
}
}
이렇게 검색부분은 끝났습니다 😱
그럼 이제 tableView의 Cell을 선택하여 Location의 정보를 가져와 봅시다 !!
extension ViewController: UITableViewDelegate{
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: true) // 선택 표시 해제
if let suggestion = completerResults?[indexPath.row] {
search(for: suggestion)
}
}
}
private func search(for suggestedCompletion: MKLocalSearchCompletion) {
let searchRequest = MKLocalSearch.Request(completion: suggestedCompletion)
search(using: searchRequest)
}
private func search(using searchRequest: MKLocalSearch.Request) {
// 검색 지역 설정
searchRequest.region = searchRegion
// 검색 유형 설정
searchRequest.resultTypes = .pointOfInterest
// MKLocalSearch 생성
localSearch = MKLocalSearch(request: searchRequest)
// 비동기로 검색 실행
localSearch?.start { [unowned self] (response, error) in
guard error == nil else {
return
}
// 검색한 결과 : reponse의 mapItems 값을 가져온다.
self.places = response?.mapItems[0]
print(places?.placemark.coordinate) // 위경도 가져옴
}
}
끝이났습니다 👏🏻⠀검색한 결과를 tableView에 표현하는건 어렵지 않지만 선택한 Location의 정보를 가져오는 부분이 조금 헷갈리긴하네요 ..
MKLocalSearchCompletion -> MKLocalSearch.Request -> MKLocalSearch의 과정을 거쳐 값을 가져와야 되는 ... 😅
와 장소 검색 진짜 열심히 찾고 있었는데 너무 감사합니다!!!!