mapView์ ์ ์ ๋ฅผ ํ์ํ๊ณ , ํ์ ์ด๋ฏธ์ง๋ฅผ ๋ณ๊ฒฝํ๋ฉฐ ์ค์๊ฐ์ผ๋ก ์ ๋ฐ์ดํธ๋ฅผ ํด๋ณธ๋ค.
Annotation ๋ชจ๋ธ์ ์์ฑํ๋ค. ์ด ๋ชจ๋ธ์ uid์ coordinate๋ฅผ ๊ฐ์ง๊ณ ์๋ค. ์์น๊ฐ์ ๊ณ์ ๋ณ๊ฒฝ์ด ๋๋ฏ๋ก dynamic์ ๋ถ์ธ๋ค. dynamicํค์๋๋ ๋ชจ๋ธ ๋ณ์์ ๋ํ ๋ณ๊ฒฝ ์ฌํญ์ Realm์ ์๋ฆฌ๊ณ , ๊ฒฐ๊ณผ์ ์ผ๋ก ์ด๋ฅผ ๋ฐ์ดํธ ๋ฒ ์ด์ค์ ๋ฐ์ํ ์ ์๋๋ก ํ๋ค.
import MapKit
class Annotation: NSObject, MKAnnotation {
var uid: String
dynamic var coordinate: CLLocationCoordinate2D
init(uid: String, coordinate: CLLocationCoordinate2D) {
self.uid = uid
self.coordinate = coordinate
}
func updateAnnotationPosition(withCoordinate coordinate: CLLocationCoordinate2D) {
UIView.animate(withDuration: 0.2) {
self.coordinate = coordinate
}
}
}
Service ๋ด๋ถ์ fetchDrivers ํจ์์ด๋ค. ์ด ํจ์๋ ์ ์ ์ ์์น๋ฅผ ๋ฐ์ ๊ทผ์ฒ์ ์ด์ ์๋ค์ fetchํ๋ ํจ์์ด๋ค. ํ์ด์ด๋ฒ ์ด์ค์์ ์ ์ ์ ์์น์์ ๋ฐ๊ฒฝ 50์ด๋ด์ ์ด์ ์์ ์์น๊ฐ๋ค์ ๊ด์ฐฐํ๋ค. ์ด์ ์์ ์์น๊ฐ ๋ณ๊ฒฝ๋๋ฉด, ๋ณ๊ฒฝ๋ ์์น์ ์ด์ ์๋ฅผ ๋ฐํํ๋ค.
*์ด์ ์๊ฐ ๋ฐ๊ฒฝ์ ๋ฒ์ด๋ฌ์ ๋ ๋งํฌ๋ฅผ ์ง์ฐ๋ ๊ธฐ๋ฅ์ ๋ฐ๋ก ์ถ๊ฐํด์ผ ํ ๊ฒ ๊ฐ๋ค.
import Firebase
import CoreLocation
import GeoFire
struct Service {
static let shared = Service()
// location -> nearby drivers
func fetchDrivers(location: CLLocation, completion: @escaping(User) -> Void) {
let geoFire = GeoFire(firebaseRef: REF_DRIVER_LOCATIONS)
REF_DRIVER_LOCATIONS.observe(.value) { snapshot in
geoFire.query(at: location, withRadius: 50).observe(.keyEntered, with: { (uid, location) in
self.fetchUserData(uid: uid) { user in
var driver = user
driver.location = location
completion(driver)
}
})
}
}
}
๋ทฐ๊ฐ ๋ก๋๋๋ฉด fetchDrivers ํจ์๋ฅผ ์คํํ๋ค. ์ ์ ์ ์์น๊ฐ์ ์์์ ๋ง๋ fetchDriversํจ์์ ์ฃผ๊ณ ๊ทผ์ฒ ์ด์ ์๋ค์ ๋ฐ๋๋ค. ๊ฐ๊ฐ ์ด์ ์์ ์์น๊ฐ์ ํตํด annotation(ํ์)๋ฅผ ๋ง๋ ๋ค. driverIsVisible์ด false์ผ ๋๋ง ํ์ํ๋ค. driverIsVisible์ Bool๊ฐ์ผ๋ก
๋งต๋ทฐ์ ์๋ ํ์๋ค์ค์ ํด๋น ์ด์ ์ uid์ ๊ฐ์ ํ์๋ค๋ง ์ ๋ฐ์ดํธ๋ฅผ ํ๊ณ , ๋งต๋ทฐ์ ํด๋น ์ด์ ์์ ํ์๊ฐ ์๋ค๋ฉด ํ์๋ฅผ ์ถ๊ฐํ๋ค.
override func viewDidLoad() {
super.viewDidLoad()
...
fetchDrivers()
}
// location -> drivers -> add annotations
private func fetchDrivers() {
guard let location = sharedLocationManager?.location else { return }
Service.shared.fetchDrivers(location: location) { driver in
guard let coordinate = driver.location?.coordinate else { return }
let annotation = DriverAnnotation(uid: driver.uid, coordinate: coordinate)
// Update driver annotation
var driverIsVisible: Bool {
return self.mapView.annotations.contains { annotation -> Bool in
guard let driverAnno = annotation as? DriverAnnotation else { return false }
if driverAnno.uid == driver.uid {
driverAnno.updateAnnotationPosition(withCoordinate: coordinate)
return true
}
return false
}
}
if !driverIsVisible {
self.mapView.addAnnotation(annotation)
}
}
}
annotation์ ๊ธฐ๋ณธ ์ด๋ฏธ์ง(๋นจ๊ฐ ์์ ์๋ ํฐ์ ํ)๋ง๊ณ ๋ฐฉํฅ ์ด๋ฏธ์ง๋ก ๋ณ๊ฒฝํ์๋ค.
extension HomeController: MKMapViewDelegate {
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
if let annotation = annotation as? DriverAnnotation {
let view = MKAnnotationView(annotation: annotation, reuseIdentifier: DRIVER_ANNOTATION)
view.image = UIImage(systemName: "location.circle.fill")
return view
}
return nil
}
}
์๋ง ์ดํ์ ํฐ ํ ๋๋ฆฌ๋ฅผ ์ถ๊ฐํ ํ ๊ทธ๋ฆผ์๋ฅผ ๋ฃ๊ณ , ๋งค์นญ๋ ์ด์ ์์ ํ์๋ ์์์ ๋ณ๊ฒฝํ๊ณ ์ ์ ์์ ๊ฑฐ๋ฆฌ๊ฐ ๋ฉ๋ฉด alpha๊ฐ์ ์ค์ด๋๊ฐ ํ ๊ฒ ๊ฐ๋ค. ์ด์ ์๊ฐ ๊ฐ๋ ๋ฐฉํฅ์ ๋ฐ๋ผ(์ด์ ์์น๊ฐ๊ณผ ํ์ฌ ์์น๊ฐ์ ์ฐจ์ด๋ฅผ ํตํด ๋ฐฉํฅ์ ์ป์) ์ ํ์์ ๋ฐฉํฅ์ ๋ณ๊ฒฝํ๋ ๊ฒ๋ ์์ ์ด๋ค. ์ด๋ฐ ๋ํ ์ผ๋ค์ ํ๋ก์ ํธ๊ฐ ๊ฑฐ์ ๋๋๋ฉด ์ถ๊ฐํ๊ณ , ๋ฐ๋ก ๋ฒจ๋ก๊ทธ์ ์ ๋ฆฌํ๊ฒ ๋ค.