오직 장소 검색 기능을 위해 사용한 MapKit
MKLocalSearch 와 start(completionHandler:) 를 활용해 장소를 검색하고, 결과를 [MKMapItem] 형태로 받아올 수 있다.
아래는 공식문서에 소개되어있는 검색 예제
let searchRequest = MKLocalSearch.Request()
searchRequest.naturalLanguageQuery = "coffee"
// Set the region to an associated map view's region.
searchRequest.region = myMapView.region
let search = MKLocalSearch(request: searchRequest)
search.start { (response, error) in
guard let response = response else {
// Handle the error.
}
for item in response.mapItems {
if let name = item.name,
let location = item.placemark.location {
print("\\(name): \\(location.coordinate.latitude),\\(location.coordinate.longitude)")
}
}
}
async throws 형태의 메서드도 지원하지만 네트워크 관련해서 아직은 팀에서 async 도입에 대해 논의해보지 않았으므로 completion handler가 있는 메서드로 “회귀”했다.
트러블슈팅
Region 설정에서 발생한 문제 (메모리 릭, 검색 범위)
장소 검색의 근간이 되는 맵뷰가 존재하고, 해당 범위에서만 검색하고 싶을 때 지역을 설정한다..는 것 같다. 처음엔 무조건 region도 설정해줘야 동작하는 줄 알고 사용하지도 않는 맵뷰를 만들어서 해당 맵뷰의 region으로 일단 설정했는데 아래와 같은 경고가 떴다.
[Memory] Resetting zone allocator with allocations still alive
Resetting zone allocator with allocations still alive
- 처음에는 위의 글처럼 removeAnnotations를 해서 맵뷰 내에서 필요 없는 annotation들을 제거해주는 방식을 썼지만 이것도 근본적인 해결책은 안됐고 오히려 왜 이거랑 메모리가 관련이 있단 걸까 하는 궁금증만 추가됨
- removeAnnotations과 메모리의 연관관계가 있을까?
- ⇒ 우선은 MKMapView를 사용하게 될 때 메모리 릭이 발생한다면 뷰컨이 deinit 될 때 설정된 델리게이트나 annotations를 모두 제거해줘야 한다.. 정도로 이해하고 마무리했다.
- 두번째는 region을 반드시 지정해줘야할 필요가 있나 싶어 생성했던 MKMapView 생성 부분과 region 설정을 바꿔줬더니 더 이상 워닝이 나지 않았다.. 역시 맵뷰 문제가 맞았던 듯.
- 하지만 이것 역시 근본적인 해결책이 아닌데다가 2주쯤 뒤에 진짜로 MKMapView를 사용해야할 일이 있기 때문에 메모리 릭을 확실히 잡을 방법을 찾아야 할 듯 하다.
request.region = MKMapView().region // 이런 느낌으로 되어 있던 걸
request.region = MKCoordinateRegion(MKMapRect.world) // 이렇게 수정함
- 그리고 궁금한 건데 region을 설정하지 않았을 때 오히려 검색 결과가 더 현재 위치와 가깝게 나타났다. 이건 왜일까..?.. MKMapView를 단순히 생성만 해서 사용해서일까? 하지만 MKMapView를 생성만 했다면 결국 세계 전체 범위를 기준으로 삼을 것이고 이건 결국 region을 지정해주지 않은 것과 결과가 같게 나와야한다고 생각했는데(뇌피셜^^) 왜 지정해주지 않았을 때 더 정확도가 높았을까? 알 수가 없는 노릇.. 공식문서를 탐독해야겠다.⇒ MKLocalSearch의 검색엔진 로직 때문일 수도 있겠다는 생각이 들었다.
- ⇒ 그리고 이건 알아낸 게 없었다.. 공식문서에서도 region을 지정해주면 검색 범위를 더 좁힐 수 있어용^^하고만 나와있고 지정해주지 않았을 때 같은 내용은 나와 있지 않았다. 그리고 다른 곳 어디에도…흑흑
⬇️⬇️⬇️ 문제의 공식문서 ⬇️⬇️⬇️
너 너무 많이 호출함ㅇㅇ
장소 검색도 결국 비동기 호출이다보니 호출에 제약이 있는 듯 했다. UISearchController를 도입하면서 UISearchResultsUpdating을 사용해봤는데 글자 하나 입력할 때마다 실시간 검색이 되어서 일정 시간 내 호출 한도를 가뿐히 초과해버리고 말았다. 한도가 어느정도인지는 제대로 확인 못했음.. 사실 한도가 있는 것도 몰랐
하여튼 그래서 UISearchResultsUpdating 대신 UISearchBarDelegate의 didEndEditing 메서드를 사용해 입력이 모두 끝나고 Search 버튼을 터치했다면 검색 결과를 뿌리도록 수정했다.
묘하게.. 정확도가 떨어지는 검색결과…
- MapKit API 데이터소스에 우리나라 장소 정보가 별로 없는 건지 뭔지 모르겠지만 묘하게 검색 결과의 정확도가 떨어진다..
- 에버랜드라고 검색하면 안나오는데 Everland라고 검색하면 나오기도 함ㅎㅎ..ㅎㅎㅎㅎ
- 하지만 다른 분들의 테스트들을 보니 결과가 나름 잘 나오는 것 같다!
'iOS' 카테고리의 다른 글
[iOS] CALayer에 CAAnimation 적용하기 (0) | 2022.12.17 |
---|---|
[iOS] 알고보면 어렵지 않은 커스텀 차트 만들기 (0) | 2022.12.14 |
[iOS] UIView Draw Cycle (0) | 2022.12.06 |
[iOS] Local Push Notification 활용해보기 (0) | 2022.12.05 |
[iOS] MVVM 폴더 구조(Folder Structure) 알아보기 (0) | 2022.05.29 |