【SwiftUI】Mapkit을 사용한 위치 정보의 취득과 핀의 표시

소개



SwiftUI에서 Mapkit과 Firebase를 사용하여 위치 정보를 데이터베이스에 저장하는 것을 목적으로 한다.
이번은 SwiftUI로 현재 위치를 취득해, 지도를 표시하는 곳까지를 기재.
Firebase를 도입하는 방법은 이전 기사를 참조하십시오.

참고 기사
【SwiftUI】CocoaPods 도입 순서와 Firebase의 설정

개발 환경



OSX 10.15.7 (Catalina)
Xcode 12.0.1
CocoaPods 1.10.0

Mapkit 가져오기 및 지도 표시까지



Mapkit 및 CoreLocation을 가져옵니다.
Alert는 위치 정보의 취득을 설정할 수 없었던 경우에 통지를 실시하도록 설정.

ContentView.swift
import SwiftUI
import Firebase

// 以下の行を追加
import CoreLocation
import MapKit

struct ContentView: View {
    // 以下を追記
    @State var manager = CLLocationManager()
    @State var alert = false

    var body: some View {
        // 以下の行を追加
        // ContentViewに地図を表示
        mapView(manager: $manager, alert: $alert).alert(isPresented: $alert) {

            Alert(title: Text("Please Enable Location Access In Setting Panel!!!"))
        }
    }
}

// MKMapViewの設定

mapView 만들기



지도 표시에는 makeUIView, updateUIView 설정이 필요합니다.

【SwiftUI】MapKit을 도입하여 지도를 표시한다
를 참고로 하면 makeUIView의 곳은 code 의 부분은 MKMapView(frame: .zero) 를 기재하는 것만으로 지도 표시는 가능합니다. 이번에는 위치 정보를 얻기 위해 showsUserLocationtrue로 설정했습니다.

makeCoordinator는 커스텀 인스턴스를 작성해, makeUIView(context:) 메소드를 호출하기 전에 이 메소드를 호출합니다. makeCoordinator는 클래스에서 설정한 코디네이터를 제공합니다.

ContentView.swift
// MKMapViewの設定
struct mapView : UIViewRepresentable {
    typealias UIViewType = MKMapView

    @Binding var manager : CLLocationManager
    @Binding var alert : Bool

    let map = MKMapView()

    func makeCoordinator() -> mapView.Coordinator {

        return mapView.Coordinator(parent1: self)
    }

    func  makeUIView(context: UIViewRepresentableContext<mapView>) -> MKMapView {
        // Tokyo 35.6804° N, 139.7690° E
        let center = CLLocationCoordinate2D(latitude: 35.6804, longitude: 139.7690)
        let region = MKCoordinateRegion(center: center, latitudinalMeters: 10000, longitudinalMeters: 10000)
        map.region = region

        manager.delegate = context.coordinator
        manager.startUpdatingLocation()
        map.showsUserLocation = true
        manager.requestWhenInUseAuthorization()
        return map
    }

    func updateUIView(_ uiView: MKMapView, context: UIViewRepresentableContext<mapView>) {

    }

    class Coordinator: NSObject, CLLocationManagerDelegate {

        var parent : mapView

        init(parent1 : mapView) {

            parent = parent1
        }

        func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {

            if status == .denied{

                parent.alert.toggle()
                print("denied")
            }
        }

        func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {

            let location = locations.last

            let point = MKPointAnnotation()

            let georeader = CLGeocoder()
            georeader.reverseGeocodeLocation(location!) { (places, err) in

                if err != nil {

                    print((err?.localizedDescription)!)
                    return
                }

                let place = places?.first?.locality
                point.title = place
                point.subtitle = "Current Place"
                point.coordinate = location!.coordinate
                self.parent.map.removeAnnotations(self.parent.map.annotations)
                self.parent.map.addAnnotation(point)

                let region = MKCoordinateRegion(center: location!.coordinate, latitudinalMeters: 10000, longitudinalMeters: 100000)
                print(region)
                self.parent.map.region = region

            }
        }
    }
}

locationManager에서, 위치 정보를 취득해, 지도상에 핀을 떨어뜨려, 표시하는 설정으로 하고 있습니다. simulator를 사용하면 핀이 떨어지지만 SwiftUI 화면의 미리보기 화면에는 표시되지 않습니다. 시뮬레이터에서는 GPS 정보를 얻을 수 없었지만 실제 기기에서 확인한 결과 현재 위치를 나타내는 핀이 표시되었습니다.

여기에서는 CLGeocoder를 호출하고 있기 때문에, 역지오코딩을 실시해, 지명을 표시하는 것도 가능합니다. 그 밖에도 핀을 표시하는 방법도 여기를 변경하면 구현이 가능합니다.
여기는 향후 구현합니다.

Xcode 프로젝트의 'info.plist'에 추가





Privacy - Location Usage Description
개발자에게 허가를 준다. 왜 사용자의 위치 정보를 얻는 이유를 설명합니다.

[Deprecated] Privacy - Location Usage Description (NSLocationUsageDescription) - Allows the developer to describe why the app wants to access the user location. NOTE: This key has been deprecated in iOS 8 (and greater). Use NSLocationDescription

Privacy - Location When In Use Usage Description
개발자에게 허가를 준다. 앱 사용 중 사용자의 위치 정보를 얻는 이유를 설명합니다.

Privacy - Location When In Use Usage Description (NSLocationWhenInUseUsageDescription) - Allows the developer to describe why the app wants to access the user's location while it is running.



"Location When In Use Usage Description"의 Value를 편집하고 문자열을 입력하면 처음 시작할 때 확인 화면에서 문자를 표시할 수 있습니다.
아래의 시뮬레이터 이미지 참고.

미리보기에서 확인하고지도보기



현재 위치 정보를 얻을 수 있습니다.
Simulator를 시작하면 처음에 "위치 정보 가져오기"권한이 필요합니다.



첫 부팅 화면


위치 정보 취득 및 핀 표시
simulator에서 GPS 취득을 할 수 없어 왜인지, 샌프란시스코가 표시되고 있다.


디버그시에 [GEOAddressObject] [NSLocale currentLocale] failed for NSLocaleCountryCode@ 의 에러가 표시되는 것은 simulator의 「설정」→「일반」→「언어와 지역」의 곳에서 「지역」에 일본을 등록하면, 에러는 나오지 않게 됩니다.

이상입니다.

좋은 웹페이지 즐겨찾기