🗺️

SwiftUI の Map の interaction を無効にする方法

2022/08/21に公開

SwiftUI には Map View を手軽に表示できる Map API があります。

この Map は以下のようにすれば利用することができます。

struct AppleParkMap: View {
     
    @State private var region = MKCoordinateRegion(
        center: CLLocationCoordinate2D(latitude: 37.334_900,
                                       longitude: -122.009_020),
        latitudinalMeters: 750,
        longitudinalMeters: 750
    )
    
    var body: some View {
        Map(coordinateRegion: $region)
    }
}

上では Map(coordinateRegion:) という initializer を利用していますが、Map には他にも現時点で以下のような initializer が存在しています。

init(coordinateRegion: Binding<MKCoordinateRegion>, interactionModes: MapInteractionModes, showsUserLocation: Bool, userTrackingMode: Binding<MapUserTrackingMode>?)

init<Items, Annotation>(coordinateRegion: Binding<MKCoordinateRegion>, interactionModes: MapInteractionModes, showsUserLocation: Bool, userTrackingMode: Binding<MapUserTrackingMode>?, annotationItems: Items, annotationContent: (Items.Element) -> Annotation)

init(mapRect: Binding<MKMapRect>, interactionModes: MapInteractionModes, showsUserLocation: Bool, userTrackingMode: Binding<MapUserTrackingMode>?)

init<Items, Annotation>(mapRect: Binding<MKMapRect>, interactionModes: MapInteractionModes, showsUserLocation: Bool, userTrackingMode: Binding<MapUserTrackingMode>?, annotationItems: Items, annotationContent: (Items.Element) -> Annotation)

色々な initializer がありますが、最初に紹介したコードで実行してみると、Map が gesture で操作できるようになっています。
この gesture による interaction は、Map initializer の interactionModes によって制御できるものとなっています。

例えば

init(coordinateRegion:interactionModes:showsUserLocation:userTrackingMode:)

この initializer であれば、

init(
    coordinateRegion: Binding<MKCoordinateRegion>,
    interactionModes: MapInteractionModes = .all,
    showsUserLocation: Bool = false,
    userTrackingMode: Binding<MapUserTrackingMode>? = nil
) where Content == _DefaultMapContent

のように interactionModes に default value として .all が指定されているため、Map(coordinateRegion: $region) のように扱うと Map が interaction 可能な形になっていました。

では、MapInteractionModes についても詳しく見てみましょう。

MapInteractionModes はドキュメントからも以下の 3 つの static property を持っていることがわかります。

  • all
    • The map allows all interaction modes.
  • pan
    • The map allows the user to pan.
  • zoom
    • The map allows the user to zoom.

それぞれ、何らかの interaction を有効にするものに見えるので、最初 interaction を無効にしたい時はどうすれば良いのか少し悩みました。

しかし、ドキュメントをよく見てみると Overview に以下のような記述がありました。

A user can’t interact with a map if the option set is empty.

つまり MapInteractionModesOptionSet であるため、empty にすれば interaction を無効にできるということです。

struct AppleParkMap: View {
    // ...
    
    var body: some View {
        Map(
	    coordinateRegion: $region,
	    interactionModes: []
	)
    }
}

これで Map の interaction が無効になります。

参考

Discussion