🗺MapViewで📌コメントの表示とリアルタイム更新


n/a.ターゲット


mapViewにユーザを表示し、表示画像を変更してリアルタイムで更新します.

Annotationモデルの作成


Annotationモデルを作成します.このモデルにはuidと座標があります.位置値は変更を続行するため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
        }
    }
    
}

フローティングコメント


サービス内部のfetchDrivers関数.この関数はプレイヤーの位置を受信し、近くの運転手を取り出す関数です.Firebaseでは、プレイヤーの位置から半径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関数にユーザの位置値を与え、近くの運転手を受信します.それぞれ運転者の位置値からコメント(表示)を作成します.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)
        }
    }
}

コメント画像の変更



注記の基本画像(赤の丸の白いピン)を方向画像に変更します.
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値が小さくなるかもしれません.運転手が歩く方向(以前の位置値と現在の位置値の違いで方向を得る)に応じて、低マークの方向を変更する計画です.これらの詳細などはプロジェクトが終わってから追加し、ブログに整理します.