2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

MapKit for SwiftUI の scope の使いどころ

Last updated at Posted at 2023-10-24

前説

iOS17から、MapKitがSwiftUIで定義することができます。

単純にマップを表示する場合は、以下のコードで表示できます。

import SwiftUI
import MapKit

struct ContentView: View {
    
    // MARK: - State
    
    // MARK: - Properties
    
    // MARK: - View
    var body: some View {
        VStack {
            Map()
        }
    }
}

地図を表示するだけならこれでいいのですが、 公式ドキュメント を見ていると scope を初期化時に指定することができます。この scope は、Namespaece.IDを指定して、デフォルトは nil です。

なんとなくMapに名前空間を与えている印象はありますが、この scope はどのように活用できるのでしょうか?

MapContorol における scope の活用

MapContorolは、例えば、ユーザーの現在地に地図を移動するボタンや、地図が向いている方向を示すコンパスアイコンのことです。これらを 地図とは違う場所に表示 したい場合に scope を活用します。

以下は、サンプルコードです。

struct ContentView: View {
    
    // MARK: - State
    @Namespace var namespace
    
    // MARK: - Properties
    
    // MARK: - View
    var body: some View {
        VStack {
            Map(scope: namespace)
            
            HStack {
                // コンパス
                MapCompass(scope: namespace)
                
                // ピッチトグル
                MapPitchToggle(scope: namespace)
                
                // 地図のスケール表示
                MapScaleView(scope: namespace)
                
                // 現在位置に移動させるボタン
                MapUserLocationButton(scope: namespace)
            }
        }
        .mapScope(namespace) // これを忘れずに記載
    }
}

Stateとして @Namespace を宣言しておきます。そして、Mapを初期化する際に namespacescope の引数として渡します。

VStack の中に、コンパス、ピッチトグル、地図のスケール(縮尺)表示、現在地に移動させるボタンを HStack で宣言します。これらは、ぞれぞれ地図の外に表示されることになります(後述のデモを参照)。また、それぞれの構造体に、先程宣言した namespacescope の引数として渡します。

そして、VStackに、mapScopeモディファイアを宣言して namespace を渡します。

これをすることで、地図の動きに合わせて 地図外にコンパスを表示 したり、 地図外にある現在地ボタンを押してユーザーの現在位置に地図を移動 したりすることができます。

デモ

実際に動かすと以下のようになります(現在地ボタンは、アプリ側で位置情報の許可が有効になっていないと動作しません)。

mapkit-swiftui-scope-demo.gif

補足

純粋に地図の上に位置情報ボタンなどを表示したい場合は、 scope を使用せず以下のように宣言します。

import SwiftUI
import MapKit

struct ContentView: View {
    
    // MARK: - State
    
    // MARK: - Properties
    
    // MARK: - View
    var body: some View {
        VStack {
            Map()
                .mapControls {
                    MapUserLocationButton()
                }
        }
    }
}

プレビュー.PNG

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?