๐Ÿ—บMapView์— ๐Ÿ“Œannotation ํ‘œ์‹œํ•˜๊ณ  ์‹ค์‹œ๊ฐ„ ์—…๋ฐ์ดํŠธํ•˜๊ธฐ

sangheeยท2021๋…„ 9์›” 4์ผ
0

๐ŸšฉiOS

๋ชฉ๋ก ๋ณด๊ธฐ
16/18
post-thumbnail

๋ชฉํ‘œ

mapView์— ์œ ์ €๋ฅผ ํ‘œ์‹œํ•˜๊ณ , ํ‘œ์‹œ ์ด๋ฏธ์ง€๋ฅผ ๋ณ€๊ฒฝํ•˜๋ฉฐ ์‹ค์‹œ๊ฐ„์œผ๋กœ ์—…๋ฐ์ดํŠธ๋ฅผ ํ•ด๋ณธ๋‹ค.

Annotation ๋ชจ๋ธ ๋งŒ๋“ค๊ธฐ

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
        }
    }
    
}

annotation ๋„์šฐ๊ธฐ

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 ์ด๋ฏธ์ง€ ๋ณ€๊ฒฝํ•˜๊ธฐ

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๊ฐ’์„ ์ค„์ด๋˜๊ฐ€ ํ•  ๊ฒƒ ๊ฐ™๋‹ค. ์šด์ „์ž๊ฐ€ ๊ฐ€๋Š” ๋ฐฉํ–ฅ์— ๋”ฐ๋ผ(์ด์ „ ์œ„์น˜๊ฐ’๊ณผ ํ˜„์žฌ ์œ„์น˜๊ฐ’์˜ ์ฐจ์ด๋ฅผ ํ†ตํ•ด ๋ฐฉํ–ฅ์„ ์–ป์Œ) ์ € ํ‘œ์‹œ์˜ ๋ฐฉํ–ฅ์„ ๋ณ€๊ฒฝํ•˜๋Š” ๊ฒƒ๋„ ์˜ˆ์ •์ด๋‹ค. ์ด๋Ÿฐ ๋””ํ…Œ์ผ๋“ค์€ ํ”„๋กœ์ ํŠธ๊ฐ€ ๊ฑฐ์˜ ๋๋‚˜๋ฉด ์ถ”๊ฐ€ํ•˜๊ณ , ๋”ฐ๋กœ ๋ฒจ๋กœ๊ทธ์— ์ •๋ฆฌํ•˜๊ฒ ๋‹ค.

profile
๐Ÿ‘ฉโ€๐Ÿ’ป

0๊ฐœ์˜ ๋Œ“๊ธ€