이 가이드를 사용하여 앱이 사용자가 경로를 따라 이동할 때 변경되는 다양한 이벤트를 수신 대기하고 이에 응답하도록 설정하세요. 이 가이드에서는 경로 정의는 다루지 않고 경로의 이벤트에 응답하는 방법만 다룹니다.
개요
iOS용 Navigation SDK는 사용자 위치, 경로의 상태, 중요한 시간 및 거리 데이터와 연결된 리스너를 제공합니다. 지도의 뷰 컨트롤러에서 앱은 이러한 리스너의 프로토콜인 GMSRoadSnappedLocationProviderListener
및 GMSNavigatorListener
를 채택해야 합니다.
다음 목록에는 탐색 이벤트에 사용할 수 있는 리스너 메서드가 나와 있습니다.
GMSNavigatorListener.didArriveAtWaypoint
: 대상에 도달할 때 트리거됩니다.GMSNavigatorListener.navigatorDidChangeRoute
: 경로가 변경될 때 트리거됩니다.GMSNavigatorListener.didUpdateRemainingTime
: 안내가 활성화되어 있는 동안 다음 대상까지의 시간이 변경될 때마다 반복적으로 호출됩니다.GMSNavigatorListener.didUpdateRemainingDistance
: 안내가 활성화되어 있는 동안 다음 대상까지의 거리가 변경될 때마다 반복적으로 호출됩니다.GMSNavigatorListener.didUpdateDelayCategory
: 안내가 활성화된 동안 다음 대상까지의 지연 시간 카테고리가 변경될 때 호출됩니다.GMSNavigatorListener.didChangeSuggestedLightingMode
: 예상 조명 조건이 업데이트될 때 트리거됩니다. 예를 들어 사용자의 현재 위치에 밤이 되면 조명이 변경됩니다.GMSNavigatorListener.didUpdateSpeedingPercentage
: 운전자가 속도 제한을 초과할 때 트리거됩니다.GMSRoadSnappedLocationProviderListener.didUpdateLocation
: 사용자의 위치가 변경될 때 반복적으로 호출됩니다.
코드 보기
이벤트 리스너의 Swift 코드를 표시하거나 숨깁니다.
/* * Copyright 2020 Google Inc. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import GoogleNavigation import UIKit class ViewController: UIViewController, GMSNavigatorListener, GMSRoadSnappedLocationProviderListener { var mapView: GMSMapView! var locationManager: CLLocationManager! override func loadView() { locationManager = CLLocationManager() let camera = GMSCameraPosition.camera(withLatitude: 47.67, longitude: -122.20, zoom: 14) mapView = GMSMapView.map(withFrame: CGRect.zero, camera: camera) // Add listeners for GMSNavigator and GMSRoadSnappedLocationProvider. mapView.navigator?.add(self) mapView.roadSnappedLocationProvider?.add(self) // Set the time update threshold (seconds) and distance update threshold (meters). mapView.navigator?.timeUpdateThreshold = 10 mapView.navigator?.distanceUpdateThreshold = 100 // Show the terms and conditions. let companyName = "Ride Sharing Co." GMSNavigationServices.showTermsAndConditionsDialogIfNeeded( withCompanyName: companyName ) { termsAccepted in if termsAccepted { // Enable navigation if the user accepts the terms. self.mapView.isNavigationEnabled = true // Request authorization to use location services. self.locationManager.requestAlwaysAuthorization() // Request authorization for alert notifications which deliver guidance instructions // in the background. UNUserNotificationCenter.current().requestAuthorization(options: [.alert]) { granted, error in // Handle denied authorization to display notifications. if !granted || error != nil { print("Authorization to deliver notifications was rejected.") } } } else { // Handle the case when the user rejects the terms and conditions. } } view = mapView makeButton() } // Create a route and start guidance. @objc func startNav() { var destinations = [GMSNavigationWaypoint]() destinations.append( GMSNavigationWaypoint.init( placeID: "ChIJnUYTpNASkFQR_gSty5kyoUk", title: "PCC Natural Market")!) destinations.append( GMSNavigationWaypoint.init( placeID: "ChIJJ326ROcSkFQRBfUzOL2DSbo", title: "Marina Park")!) mapView.navigator?.setDestinations(destinations) { routeStatus in guard routeStatus == .OK else { print("Handle route statuses that are not OK.") return } self.mapView.navigator?.isGuidanceActive = true self.mapView.cameraMode = .following self.mapView.locationSimulator?.simulateLocationsAlongExistingRoute() } mapView.roadSnappedLocationProvider?.startUpdatingLocation() } // Listener to handle continuous location updates. func locationProvider( _ locationProvider: GMSRoadSnappedLocationProvider, didUpdate location: CLLocation ) { print("Location: \(location.description)") } // Listener to handle speeding events. func navigator( _ navigator: GMSNavigator, didUpdateSpeedingPercentage percentageAboveLimit: CGFloat ) { print("Speed is \(percentageAboveLimit) above the limit.") } // Listener to handle arrival events. func navigator(_ navigator: GMSNavigator, didArriveAt waypoint: GMSNavigationWaypoint) { print("You have arrived at: \(waypoint.title)") mapView.navigator?.continueToNextDestination() mapView.navigator?.isGuidanceActive = true } // Listener for route change events. func navigatorDidChangeRoute(_ navigator: GMSNavigator) { print("The route has changed.") } // Listener for time to next destination. func navigator(_ navigator: GMSNavigator, didUpdateRemainingTime time: TimeInterval) { print("Time to next destination: \(time)") } // Delegate for distance to next destination. func navigator( _ navigator: GMSNavigator, didUpdateRemainingDistance distance: CLLocationDistance ) { let miles = distance * 0.00062137 print("Distance to next destination: \(miles) miles.") } // Delegate for traffic updates to next destination func navigator( _ navigator: GMSNavigator, didUpdate delayCategory: GMSNavigationDelayCategory ) { print("Delay category to next destination: \(String(describing: delayCategory)).") } // Delegate for suggested lighting mode changes. func navigator( _ navigator: GMSNavigator, didChangeSuggestedLightingMode lightingMode: GMSNavigationLightingMode ) { print("Suggested lighting mode has changed: \(String(describing: lightingMode))") // Change to the suggested lighting mode. mapView.lightingMode = lightingMode } // Add a button to the view. func makeButton() { // Start navigation. let navButton = UIButton(frame: CGRect(x: 5, y: 150, width: 200, height: 35)) navButton.backgroundColor = .blue navButton.alpha = 0.5 navButton.setTitle("Start navigation", for: .normal) navButton.addTarget(self, action: #selector(startNav), for: .touchUpInside) self.mapView.addSubview(navButton) } }
이벤트 리스너의 Objective-C 코드를 표시하거나 숨깁니다.
/* * Copyright 2020 Google Inc. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #import "ViewController.h" @import GoogleNavigation; @interface ViewController () <GMSNavigatorListener, GMSRoadSnappedLocationProviderListener> @end @implementation ViewController { GMSMapView *_mapView; CLLocationManager *_locationManager; } - (void)loadView { _locationManager = [[CLLocationManager alloc] init]; GMSCameraPosition *camera = [GMSCameraPosition cameraWithLatitude:47.67 longitude:-122.20 zoom:14]; _mapView = [GMSMapView mapWithFrame:CGRectZero camera:camera]; // Add listeners for GMSNavigator and GMSRoadSnappedLocationProvider. [_mapView.navigator addListener:self]; [_mapView.roadSnappedLocationProvider addListener:self]; // Set the time update threshold (seconds) and distance update threshold (meters). _mapView.navigator.timeUpdateThreshold = 10; _mapView.navigator.distanceUpdateThreshold = 100; // Show the terms and conditions. NSString *companyName = @"Ride Sharing Co."; [GMSNavigationServices showTermsAndConditionsDialogIfNeededWithCompanyName:companyName callback:^(BOOL termsAccepted) { if (termsAccepted) { // Enable navigation if the user accepts the terms. _mapView.navigationEnabled = YES; // Request authorization to use location services. [_locationManager requestAlwaysAuthorization]; } else { // Handle the case when the user rejects the terms and conditions. } }]; self.view = _mapView; [self makeButton]; } // Create a route and initiate navigation. - (void)startNav { NSArray<GMSNavigationWaypoint *> *destinations = @[[[GMSNavigationWaypoint alloc] initWithPlaceID:@"ChIJnUYTpNASkFQR_gSty5kyoUk" title:@"PCC Natural Market"], [[GMSNavigationWaypoint alloc] initWithPlaceID:@"ChIJJ326ROcSkFQRBfUzOL2DSbo" title:@"Marina Park"]]; [_mapView.navigator setDestinations:destinations callback:^(GMSRouteStatus routeStatus){ _mapView.navigator.guidanceActive = YES; _mapView.navigator.sendsBackgroundNotifications = YES; _mapView.cameraMode = GMSNavigationCameraModeFollowing; [_mapView.locationSimulator simulateLocationsAlongExistingRoute]; }]; [_mapView.roadSnappedLocationProvider startUpdatingLocation]; } #pragma mark - GMSNavigatorListener // Listener for continuous location updates. - (void)locationProvider:(GMSRoadSnappedLocationProvider *)locationProvider didUpdateLocation:(CLLocation *)location { NSLog(@"Location: %@", location.description); } // Listener to handle speeding events. - (void)navigator:(GMSNavigator *)navigator didUpdateSpeedingPercentage:(CGFloat)percentageAboveLimit { NSLog(@"Speed is %f percent above the limit.", percentageAboveLimit); } // Listener to handle arrival events. - (void)navigator:(GMSNavigator *)navigator didArriveAtWaypoint:(GMSNavigationWaypoint *)waypoint { NSLog(@"You have arrived at: %@", waypoint.title); [_mapView.navigator continueToNextDestination]; _mapView.navigator.guidanceActive = YES; } // Listener for route change events. - (void)navigatorDidChangeRoute:(GMSNavigator *)navigator { NSLog(@"The route has changed."); } // Listener for time to next destination. - (void)navigator:(GMSNavigator *)navigator didUpdateRemainingTime:(NSTimeInterval)time { NSLog(@"Time to next destination: %f", time); } // Listener for distance to next destination. - (void)navigator:(GMSNavigator *)navigator didUpdateRemainingDistance:(CLLocationDistance)distance { double miles = distance * 0.00062137; NSLog(@"%@", [NSString stringWithFormat:@"Distance to next destination: %.2f.", miles]); } // Listener for traffic updates for next destination - (void)navigator:(GMSNavigator *)navigator didUpdateDelayCategory:(GMSNavigationDelayCategory)delayCategory { NSLog(@"Delay category to next destination: %ld.", delayCategory); } // Listener for suggested lighting mode changes. -(void)navigator:(GMSNavigator *)navigator didChangeSuggestedLightingMode:(GMSNavigationLightingMode)lightingMode { NSLog(@"Suggested lighting mode has changed: %ld", (long)lightingMode); // Change to the suggested lighting mode. _mapView.lightingMode = lightingMode; } #pragma mark - Programmatic UI elements // Add a button to the view. - (void)makeButton { // Start navigation. UIButton *navButton = [UIButton buttonWithType:UIButtonTypeCustom]; [navButton addTarget:self action:@selector(startNav) forControlEvents:UIControlEventTouchUpInside]; [navButton setTitle:@"Navigate" forState:UIControlStateNormal]; [navButton setBackgroundColor:[UIColor blueColor]]; [navButton setAlpha:0.5]; navButton.frame = CGRectMake(5.0, 150.0, 100.0, 35.0); [_mapView addSubview:navButton]; } @end
필수 프로토콜 준수 선언
뷰 컨트롤러는 탐색 메서드를 구현하기 전에 다음 프로토콜을 채택해야 합니다.
class ViewController: UIViewController, GMSNavigatorListener,
GMSRoadSnappedLocationProviderListener {
@interface ViewController () <GMSNavigatorListener,
GMSRoadSnappedLocationProviderListener>
@end
탐색 프로토콜을 채택한 후 리스너를 뷰 컨트롤러로 설정합니다. 예를 들어 viewDidLoad()
메서드에 다음 코드를 추가할 수 있습니다.
mapView.navigator?.add(self) mapView.roadSnappedLocationProvider?.add(self)
[_mapView.navigator addListener:self]; [_mapView.roadSnappedLocationProvider
addListener:self];
위치 업데이트 수신 또는 중지
지도에 사용자의 진행 상황을 표시하려면 위치 업데이트가 필요합니다.
location
인스턴스는 다음 속성을 노출합니다.
위치 속성 | 설명 |
---|---|
고도 | 현재 고도입니다. |
coordinate.latitude | 현재 도로 스냅 위도 좌표입니다. |
coordinate.longitude | 현재 도로 스냅 경도 좌표입니다. |
강의 | 현재 방향(도)입니다. |
속도 | 현재 속도입니다. |
타임스탬프 | 현재 판독값의 날짜/시간입니다. |
연속적인 위치 업데이트를 수신하려면 mapView.roadSnappedLocationProvider.startUpdatingLocation
를 호출하고 GMSRoadSnappedLocationProviderListener
를 사용하여 didUpdateLocation
이벤트를 처리합니다.
다음은 startUpdatingLocation
를 호출하는 예를 보여줍니다.
mapView.roadSnappedLocationProvider.startUpdatingLocation()
[_mapView.roadSnappedLocationProvider startUpdatingLocation];
다음 코드는 didUpdateLocation
이벤트를 처리하는 GMSRoadSnappedLocationProviderListener
를 만듭니다.
func locationProvider(_ locationProvider: GMSRoadSnappedLocationProvider,
didUpdate location: CLLocation) { print("Location: \(location.description)") }
- (void)locationProvider:(GMSRoadSnappedLocationProvider *)locationProvider
didUpdateLocation:(CLLocation *)location { NSLog(@"Location: %@",
location.description); }
앱이 백그라운드에 있을 때 위치 업데이트를 수신하려면 allowsBackgroundLocationUpdates
를 true로 설정하세요.
mapView.roadSnappedLocationProvider.allowsBackgroundLocationUpdates = true
_mapView.roadSnappedLocationProvider.allowsBackgroundLocationUpdates = YES;
도착 이벤트 감지
앱은 didArriveAtWaypoint
이벤트를 사용하여 대상에 도달했음을 감지합니다. continueToNextDestination()
를 호출한 다음 안내를 다시 사용 설정하여 안내를 재개하고 다음 중간 지점으로 이동할 수 있습니다. 앱은 continueToNextDestination()
를 호출한 후에 안내를 다시 사용 설정해야 합니다.
앱이 continueToNextDestination
를 호출하면 더 이상 이전 대상에 관한 데이터가 내비게이터에 없습니다. 경로 구간에 관한 정보를 분석하려면 continueToNextDestination()
를 호출하기 전에 탐색기에서 이를 가져와야 합니다.
다음 코드 예는 didArriveAtWaypoint
이벤트를 처리하는 메서드를 보여줍니다.
func navigator(_ navigator: GMSNavigator, didArriveAt waypoint:
GMSNavigationWaypoint) { print("You have arrived at: \(waypoint.title)")
mapView.navigator?.continueToNextDestination()
mapView.navigator?.isGuidanceActive = true }
- (void)navigator:(GMSNavigator *)navigator
didArriveAtWaypoint:(GMSNavigationWaypoint *)waypoint { NSLog(@"You have
arrived at: %@", waypoint.title); [_mapView.navigator
continueToNextDestination]; _mapView.navigator.guidanceActive = YES; }
경로 변경 업데이트 수신
경로가 변경될 때마다 알림을 받으려면 navigatorDidChangeRoute
이벤트를 처리하는 메서드를 만듭니다. GMSNavigator
의 routeLegs
및 currentRouteLeg
속성을 사용하여 새 경로에 액세스할 수 있습니다.
func navigatorDidChangeRoute(_ navigator: GMSNavigator) { print("The route has
changed.") }
- (void)navigatorDidChangeRoute:(GMSNavigator *)navigator { NSLog(@"The route
has changed."); }
도착까지의 예상 시간 업데이트 수신
목적지까지의 시간 업데이트를 연속으로 수신하려면 didUpdateRemainingTime
이벤트를 처리하는 메서드를 만듭니다. time
매개변수는 다음 대상에 도달할 때까지의 예상 시간을 초 단위로 제공합니다.
func navigator(_ navigator: GMSNavigator, didUpdateRemainingTime time:
TimeInterval) { print("Time to next destination: \(time)") }
- (void)navigator:(GMSNavigator *)navigator
didUpdateRemainingTime:(NSTimeInterval)time { NSLog(@"Time to next
destination: %f", time); }
다음 도착지에 도착하는 데 걸리는 예상 시간의 최소 변경 값을 설정하려면 GMSNavigator
에서 timeUpdateThreshold
속성을 설정하세요. 값은 초 단위로 지정됩니다. 이 속성을 설정하지 않으면 서비스는 기본값인 1초를 사용합니다.
navigator?.timeUpdateThreshold = 10
navigator.timeUpdateThreshold = 10;
목적지까지의 거리 업데이트 수신
목적지까지의 거리 업데이트를 지속적으로 수신하려면 didUpdateRemainingDistance
이벤트를 처리하는 메서드를 만듭니다. distance
매개변수는 다음 목적지까지의 예상 거리(단위: 미터)를 제공합니다.
func navigator(_ navigator: GMSNavigator, didUpdateRemainingDistance distance:
CLLocationDistance) { let miles = distance * 0.00062137 print("Distance to next
destination: \(miles) miles.") }
- (void)navigator:(GMSNavigator *)navigator
didUpdateRemainingDistance:(CLLocationDistance)distance { double miles =
distance * 0.00062137; NSLog(@"%@", [NSString stringWithFormat:@"Distance to
next destination: %.2f.", miles]); }
다음 도착지에 대한 예상 거리의 최소 변경사항을 설정하려면 GMSNavigator
에서 distanceUpdateThreshold
속성을 설정합니다 (값은 미터로 지정됨). 이 속성을 설정하지 않으면 서비스는 기본값인 1미터를 사용합니다.
navigator?.distanceUpdateThreshold = 100
navigator.distanceUpdateThreshold = 100;
교통정보 업데이트 받기
나머지 경로의 교통 흐름에 대한 지속적인 업데이트를 수신하려면 didUpdateDelayCategory
이벤트를 처리하는 메서드를 만듭니다. delayCategoryToNextDestination
호출은 0~3의 값을 제공하는 GMSNavigationDelayCategory
를 반환합니다. 카테고리 업데이트는 앱 사용자의 현재 위치를 기반으로 합니다. 트래픽 데이터를 사용할 수 없는 경우 GMSNavigationDelayCategory
는 0을 반환합니다. 숫자 1~3은 흐름이 약에서 강으로 증가함을 나타냅니다.
func navigator(_ navigator: GMSNavigator, didUpdate delayCategory:
GMSNavigationDelayCategory) { print("Traffic flow to next destination:
\(delayCategory)") }
- (void)navigator:(GMSNavigator *)navigator
didUpdateDelayCategory:(GMSNavigationDelayCategory)delayCategory {
NSLog(@"Traffic flow to next destination: %ld", (long)delayCategory); }
GMSNavigationDelayCategory
속성은 다음과 같은 지연 수준을 노출합니다.
지연 카테고리 | 설명 |
---|---|
GMSNavigationDelayCategoryNoData | 0 - 사용 불가, 트래픽 데이터 없음 또는 : |
경로를 확인할 수 있습니다. | |
GMSNavigationDelayCategoryHeavy | 1 - 심함 |
GMSNavigationDelayCategoryMedium | 2 - 중간 |
GMSNavigationDelayCategoryLight | 3 - 밝음 |
속도 위반 업데이트 수신
운전자가 속도 제한을 초과할 때 업데이트를 수신하려면 didUpdateSpeedingPercentage
이벤트를 처리하는 메서드를 만듭니다.
// Listener to handle speeding events. func navigator( _ navigator:
GMSNavigator, didUpdateSpeedingPercentage percentageAboveLimit: CGFloat ) {
print("Speed is \(percentageAboveLimit) above the limit.") }
// Listener to handle speeding events. - (void)navigator:(GMSNavigator
*)navigator didUpdateSpeedingPercentage:(CGFloat)percentageAboveLimit {
NSLog(@"Speed is %f percent above the limit.", percentageAboveLimit); }
추천 조명 모드 변경하기
예상되는 조명 변경사항에 관한 업데이트를 수신하려면 didChangeSuggestedLightingMode
이벤트를 처리하는 메서드를 만듭니다.
// Define a listener for suggested changes to lighting mode. func navigator(_
navigator: GMSNavigator, didChangeSuggestedLightingMode lightingMode:
GMSNavigationLightingMode) { print("Suggested lighting mode has changed:
\(String(describing: lightingMode))")
// Make the suggested change. mapView.lightingMode = lightingMode }
// Define a listener for suggested changes to lighting mode.
-(void)navigator:(GMSNavigator *)navigator didChangeSuggestedLightingMode:
(GMSNavigationLightingMode)lightingMode { NSLog(@"Suggested lighting mode has
changed: %ld", (long)lightingMode);
// Make the suggested change. _mapView.lightingMode = lightingMode; }