質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

Q&A

解決済

1回答

986閲覧

【Swift】地図に自分の通った経路を描画したい

matsui94

総合スコア3

Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

0グッド

0クリップ

投稿2022/08/25 08:39

編集2022/08/25 08:45

前提

Swiftを使って「一定周期で自分の位置情報を取得・蓄積して、地図に自分の通った経路を可視化する」アプリを作っています。
地図の表示と現在地の取得、リストに取得した位置情報を蓄積していく部分は実装できたのですが、自分の通った経路を描画する部分がうまく実装できません。

解決策をご存じの方おられましたら、ご教授の程よろくしお願いします。

【開発環境】
・MacBook Pro (13-inch, 2017, Two Thunderbolt 3 ports), macOS Monterey ver12.5
・Xcode ver13.4.1

実現したいこと

  • 一定周期で取得している位置情報から自分の通った移動経路を地図上に描画したい

発生している問題・エラーメッセージ

位置情報をappendしているリストを使って移動経路を線で描画(MKPolyline)しようと考えているのですが、うまくできませんでした。
位置情報がリストにappendされていることは、print出力して確認しています。
※ XcodeのシミュレータでLocationを「City Bicycle Ride」にしてアプリの動作確認をしています。

/* 位置情報の出力結果 (一部抜粋) */ locationViewModel.locationlog = [] locationViewModel.locationlog = [__C.CLLocationCoordinate2D(latitude: 37.33069642, longitude: -122.03066881), __C.CLLocationCoordinate2D(latitude: 37.33069642, longitude: -122.03066881)] locationViewModel.locationlog = [__C.CLLocationCoordinate2D(latitude: 37.33069642, longitude: -122.03066881), __C.CLLocationCoordinate2D(latitude: 37.33069642, longitude: -122.03066881), __C.CLLocationCoordinate2D(latitude: 37.33092652, longitude: -122.02322308)]

該当のソースコード

Swift

1import SwiftUI 2import MapKit 3 4@main 5struct SmartMoveTestApp: App { 6 var body: some Scene { 7 WindowGroup { 8 ContentView() 9 } 10 } 11}

Swift

1import SwiftUI 2import MapKit 3import CoreLocation 4 5struct ContentView: View { 6 @StateObject var locationViewModel = LocationViewModel() // 現在地取得クラス 7 8 var body: some View { 9 ZStack(){ 10 /* マップ */ 11 MapView() 12 .environmentObject(locationViewModel) 13 .ignoresSafeArea(.all) // セーフエリアぶち抜き 14 15 VStack{ 16 17 HStack{ 18 /* 設定ボタン */ 19 Button(action: { 20 /* --- ボタン押した時のアクション --- */ 21 }) { 22 Image("setting") 23 .resizable() // リサイズ 24 .frame(width: 40, height: 40) // 40pt*40pt 25 .clipShape(Circle()) // 円形に切り抜く 26 } 27 .padding(.all, 10.0) // パディング (全方位10pt) 28 29 Spacer() 30 } 31 32 Spacer() 33 } 34 } 35 } 36} 37 38struct ContentView_Previews: PreviewProvider { 39 static var previews: some View { 40 ContentView() 41 } 42}

Swift

1import SwiftUI 2import MapKit 3import CoreLocation 4 5struct MapView: UIViewRepresentable { 6 @EnvironmentObject var locationViewModel: LocationViewModel // 位置情報を取得しているモデル 7 8 var myMap = MKMapView() 9 10 // Coordinatorでコントローラのdelegateを管理 11 class Coordinator: NSObject, MKMapViewDelegate { 12 let parent: MapView 13 14 init(_ parent: MapView){ 15 self.parent = parent 16 } 17 18 func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer { 19 if let polyline = overlay as? MKPolyline { 20 let polylineRenderer = MKPolylineRenderer(polyline: polyline) 21 polylineRenderer.strokeColor = UIColor(red: 0, green: 0.5, blue: 1.0, alpha: 1.0) 22 polylineRenderer.lineWidth = 5.0 23 24 return polylineRenderer 25 } 26 27 return MKOverlayRenderer() 28 } 29 } 30 31 func makeUIView(context: Context) -> MKMapView { 32 myMap.delegate = context.coordinator 33 initMap() 34 return myMap 35 } 36 37 func updateUIView(_ uiView: MKMapView, context: Context) { 38 drawLocationLog() // 取得した位置情報から移動経路を描画 39 } 40 41 func initMap() { 42 /* Mapの初期化 */ 43 var region: MKCoordinateRegion = myMap.region 44 region.center = myMap.userLocation.coordinate // 表示地図の中心 == 現在地 45 region.span.latitudeDelta = 0.0035 // 縦の表示倍率のようなもの 46 region.span.longitudeDelta = 0.0035 // 横の表示倍率のようなもの 47 myMap.setRegion(region, animated: true) 48 myMap.showsUserLocation = true // 地図上に現在地を表示 49 myMap.userTrackingMode = .follow // 現在地を更新 (== トラッキング?) 50 } 51 52 func drawLocationLog() { 53 /* 位置情報ログをもとに移動経路を描く 54 locationViewModel.locationLog: 一定周期で現在地の緯度経度をappendしているリスト 55 イメージ) locationViewModel.locationLog = [ 56 __C.CLLocationCoordinate2D(latitude: 37.3304337, longitude: -122.0301625), 57 __C.CLLocationCoordinate2D(latitude: 37.33044907, longitude: -122.02969739), 58 ... ] 59 */ 60 print("locationViewModel.locationlog = ", locationViewModel.locationLog) 61 let polyLine = MKPolyline(coordinates: locationViewModel.locationLog, count: locationViewModel.locationLog.count) 62 myMap.addOverlay(polyLine) // 地図上に描画 63 } 64 65 func makeCoordinator() -> Coordinator { 66 return Coordinator(self) 67 } 68} 69 70 71struct MapView_Previews: PreviewProvider { 72 static var previews: some View { 73 MapView() 74 .ignoresSafeArea() 75 } 76}

Swift

1import CoreLocation 2import MapKit 3 4class LocationViewModel: NSObject, ObservableObject, CLLocationManagerDelegate, MKMapViewDelegate { 5 @Published var authorizationStatus: CLAuthorizationStatus // 位置情報取得許可 6 @Published var lastSeenLocation: CLLocation? // 現在地 7 @Published var locationLog: [CLLocationCoordinate2D] = [] // 移動経路を可視化するためのリスト 8 9 private let locationManager: CLLocationManager 10 11 var locationFlag = true 12 13 override init() { 14 /* 初期化処理 */ 15 locationManager = CLLocationManager() 16 authorizationStatus = locationManager.authorizationStatus // 位置情報の許可レベル 17 18 super.init() 19 locationManager.delegate = self 20 locationManager.desiredAccuracy = kCLLocationAccuracyBest // 位置情報の取得精度 21 locationManager.distanceFilter = 5 // 位置情報取得間隔 [m] 22 locationManager.allowsBackgroundLocationUpdates = true // バックグラウンド実行中も座標取得する場合、trueにする 23 locationManager.pausesLocationUpdatesAutomatically = false // 同じ場所に止まっていると判断した場合に位置情報取得を一時停止するならtrueにする 24 locationManager.startUpdatingLocation() // 位置情報の取得開始 25 requestPermission() // 位置情報の取得リクエスト処理 26 } 27 28 func requestPermission() { 29 /* リクエスト許可について */ 30 locationManager.requestWhenInUseAuthorization() 31 } 32 33 func locationManagerDidChangeAuthorization(_ manager: CLLocationManager) { 34 /* 位置情報の許可レベルの変更 */ 35 authorizationStatus = manager.authorizationStatus 36 } 37 38 func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) { 39 lastSeenLocation = locations.first // 位置情報を取得 40 41 guard let location = lastSeenLocation else { 42 /* 入力できない場合 returnされる */ 43 return 44 } 45 locationLog.append(location.coordinate) // 地図に経路を描画するために位置情報を蓄積 46 } 47}

試したこと

移動経路を描画する際、リストを一定周期でappendしていることが原因なのかなと思い、リストの中身を下記に固定して実行しました。その場合は、地図上に描画されていました。
※ リストの中身は、シミュレータを動かした際の出力結果を使っています。

Swift

1func drawLocationLog() { 2 let logTest: [CLLocationCoordinate2D] 3 logTest = [CLLocationCoordinate2D(latitude: 37.3304337, longitude: -122.0301625), 4 CLLocationCoordinate2D(latitude: 37.3304337, longitude: -122.0301625), 5 CLLocationCoordinate2D(latitude: 37.33044907, longitude: -122.02969739), 6 CLLocationCoordinate2D(latitude: 37.33045275, longitude: -122.02953296), 7 CLLocationCoordinate2D(latitude: 37.3304262, longitude: -122.02937447), 8 CLLocationCoordinate2D(latitude: 37.33039592, longitude: -122.0293017), 9 CLLocationCoordinate2D(latitude: 37.33034112, longitude: -122.02915992), 10 CLLocationCoordinate2D(latitude: 37.33030778, longitude: -122.0290151), 11 CLLocationCoordinate2D(latitude: 37.33024463, longitude: -122.02887705), 12 CLLocationCoordinate2D(latitude: 37.33023954, longitude: -122.02876063), 13 CLLocationCoordinate2D(latitude: 37.33024138, longitude: -122.02864146), 14 CLLocationCoordinate2D(latitude: 37.33024195, longitude: -122.02851527), 15 CLLocationCoordinate2D(latitude: 37.33023185, longitude: -122.02837143), 16 CLLocationCoordinate2D(latitude: 37.33022547, longitude: -122.02822335), 17 CLLocationCoordinate2D(latitude: 37.33021434, longitude: -122.02806565), 18 CLLocationCoordinate2D(latitude: 37.33019659, longitude: -122.0278974), 19 CLLocationCoordinate2D(latitude: 37.3301817, longitude: -122.02771529), 20 CLLocationCoordinate2D(latitude: 37.33017597, longitude: -122.02753152), 21 CLLocationCoordinate2D(latitude: 37.33017311, longitude: -122.02734894), 22 CLLocationCoordinate2D(latitude: 37.33017732, longitude: -122.02717143)] 23 let polyLineTest = MKPolyline(coordinates: logTest, count: logTest.count) 24 myMap.addOverlay(polyLineTest) // 地図上に描画 25 }

補足情報(FW/ツールのバージョンなど)

ここにより詳細な情報を記載してください。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

次のような感じにしたところ描画されたみたいでした。
*ポイントの行だけ抜粋しています

swift

1// *** updateUIView(_:context:)の引数で受け取るuiViewをdrawLocationLogに渡します 2drawLocationLog(uiView) // 取得した位置情報から移動経路を描画 3 4// *** uiViewを受け取ります 5func drawLocationLog(_ uiView: MKMapView) { 6 7// *** 受け取ったuiViewに対してaddOverlayをします 8uiView.addOverlay(polyLine) // 地図上に描画

makeUIView(context:)で返したインスタンスと同じものを保持していると思うのですが、
updateUIView(_:context:)で受け取るインスタンスは何か違うのでしょうかね・・

投稿2022/08/25 16:05

退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

matsui94

2022/08/26 03:22

ありがとうございます!実際に描画できたことを確認しました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問