🪶

SwiftUIマーカーを表示する

2024/09/16に公開

Mapのタップした位置にピンを立てる

Swiftポケットリファレンスのp230を参考にサンプルコードを書いてみたが、タップした場所にピンがたたなかった?

東京駅周辺を表示してタップした位置でピンを立てる仕組みのアプリを作ってみた。

主な変更点と修正は以下の通りです:

Mapビューの修正:

MapAnnotationの代わりにMapMarkerを使用して、シンプルなピンを表示します。

タップ処理の修正:

Mapビューに直接.onTapGestureを適用できないため、透明なオーバーレイを追加し、そこでタップを検出します。

座標変換の修正:

convertToCoordinate関数を新たに実装し、タップ位置を正確に座標に変換します。

東京駅周辺のマップが表示されます。
マップをタップするたびに、タップした場所に新しいピンが立ちます。
各ピンには "ピン X" という形式でユニークな名前が付けられます(ただし、マップ上には表示されません)。
タップした座標にピンが立ちます📍

import SwiftUI
import MapKit

struct IdentifiablePointAnnotation: Identifiable {
    let id = UUID()
    var annotation: MKPointAnnotation
}

struct MapSectionView: View {
    @State private var region = MKCoordinateRegion(
        center: CLLocationCoordinate2D(latitude: 35.6812, longitude: 139.7671), // 東京駅の座標
        span: MKCoordinateSpan(latitudeDelta: 0.01, longitudeDelta: 0.01)
    )
    @State private var annotations: [IdentifiablePointAnnotation] = []
    
    var body: some View {
        Map(coordinateRegion: $region, annotationItems: annotations) { place in
            MapMarker(coordinate: place.annotation.coordinate, tint: .red)
        }
        .overlay(
            Color.clear
                .contentShape(Rectangle())
                .onTapGesture { location in
                    let coordinate = convertToCoordinate(location)
                    addAnnotation(at: coordinate)
                }
        )
    }
    
    private func convertToCoordinate(_ location: CGPoint) -> CLLocationCoordinate2D {
        let mapSize = UIScreen.main.bounds.size
        let normalizedPoint = CGPoint(
            x: location.x / mapSize.width,
            y: location.y / mapSize.height
        )
        
        let newLat = region.center.latitude - (normalizedPoint.y - 0.5) * region.span.latitudeDelta
        let newLon = region.center.longitude + (normalizedPoint.x - 0.5) * region.span.longitudeDelta
        
        return CLLocationCoordinate2D(latitude: newLat, longitude: newLon)
    }
    
    private func addAnnotation(at coordinate: CLLocationCoordinate2D) {
        let newAnnotation = MKPointAnnotation()
        newAnnotation.coordinate = coordinate
        newAnnotation.title = "ピン \(annotations.count + 1)"
        annotations.append(IdentifiablePointAnnotation(annotation: newAnnotation))
        print("タップした座標: \(coordinate.latitude), \(coordinate.longitude)")
    }
}

struct MapSectionView_Previews: PreviewProvider {
    static var previews: some View {
        MapSectionView()
    }
}

最後に

何か位置情報を記録したいアプリで使えそう?

  • 気になったスポットの記録
  • わかりにくい場所にあるお店の場所

Discussion