สร้างแอปการนำทาง iOS แบบง่ายใน Swift ด้วย Google Maps Platform Navigation SDK

1. ก่อนเริ่มต้น

Codelab นี้จะสอนวิธีสร้างแอป iOS อย่างง่ายที่ใช้ SDK การนำทางของ Google Maps Platform เพื่อไปยังจุดหมายที่กำหนดค่าไว้ล่วงหน้า

แอปของคุณจะมีลักษณะดังนี้เมื่อเสร็จสิ้น

7e7c194a98d6dfa4.png

ข้อกำหนดเบื้องต้น

สิ่งที่คุณจะได้เรียนรู้

  • วิธีสร้างแอป iOS Swift อย่างง่ายที่ใช้ Navigation SDK เพื่อไปยังปลายทาง
  • วิธีผสานรวม Navigation SDK จากที่เก็บ Cocoapods ระยะไกล
  • วิธีจัดการสิทธิ์เข้าถึงตำแหน่งและข้อตกลงของผู้ใช้เกี่ยวกับข้อกำหนดสำหรับผู้ใช้ปลายทางของ Navigation SDK
  • วิธีเริ่มต้น SDK
  • วิธีตั้งค่าปลายทางและเริ่มคำแนะนำการนำทาง

สิ่งที่คุณต้องมี

  • XCode เวอร์ชันเสถียรล่าสุด
  • บัญชี Google และโปรเจ็กต์ที่เปิดใช้การเรียกเก็บเงิน
  • อุปกรณ์ iOS หรืออุปกรณ์จำลองที่ทำงานใน XCode Simulator ไม่ว่าคุณจะเลือกตัวเลือกใดก็ตาม ตัวเลือกนั้นต้องเป็นไปตามข้อกำหนดขั้นต่ำสำหรับ Navigation SDK

2. ตั้งค่า

หากยังไม่มีบัญชี Google Cloud Platform และโปรเจ็กต์ที่เปิดใช้การเรียกเก็บเงิน ให้ตั้งค่าโปรเจ็กต์ Google Cloud โดยทำตามวิธีการเริ่มต้นใช้งาน Google Maps Platform

เลือกโปรเจ็กต์ Google Cloud ในคอนโซล

ใน Cloud Console ให้คลิกเมนูแบบเลื่อนลงของโปรเจ็กต์ แล้วเลือกโปรเจ็กต์ที่ต้องการใช้สำหรับ Codelab นี้

เมนูแบบเลื่อนลงของตัวเลือกโปรเจ็กต์ใน Google Cloud Console

เปิดใช้ Navigation SDK ในโปรเจ็กต์

เปิดใช้ API และ SDK ของ Google Maps Platform ที่จำเป็นสำหรับ Codelab นี้ใน Google Cloud Marketplace

ไปที่ API และบริการ > ไลบรารีในคอนโซล Google Cloud แล้วค้นหา "Navigation SDK"

คุณควรเห็นผลการค้นหา 1 รายการ

หน้าจอคลัง API ในคอนโซล Google Cloud ซึ่งแสดงหน้า Navigation SDK

คลิก Navigation SDK เพื่อเปิดหน้ารายละเอียดผลิตภัณฑ์ คลิกเปิดใช้เพื่อเปิดใช้ SDK ในโปรเจ็กต์

ทำกระบวนการนี้ซ้ำสำหรับ Google Maps SDK สำหรับ iOS

สร้างคีย์ API

สร้างคีย์ API ในหน้าข้อมูลเข้าสู่ระบบของ Cloud Console คำขอทั้งหมดที่ส่งไปยัง Google Maps Platform ต้องมีคีย์ API ในหน้าข้อมูลเข้าสู่ระบบในคอนโซล คลิก "+สร้างข้อมูลเข้าสู่ระบบ" ที่ด้านบนของหน้า แล้วเลือก "คีย์ API" จากตัวเลือก

สำหรับการใช้งานจริง แนวทางปฏิบัติแนะนำคือตั้งค่าการจำกัดแอปพลิเคชันสำหรับคีย์ API แต่คุณจะตั้งค่าหรือไม่ก็ได้สำหรับโค้ดแล็บนี้

3. รับไฟล์โปรเจ็กต์ตัวอย่าง

ส่วนนี้จะอธิบายวิธีตั้งค่าโปรเจ็กต์แอป XCode ว่างเปล่าพื้นฐานโดยการโคลนไฟล์จากที่เก็บ GitHub สำหรับ Codelab นี้ ที่เก็บ Github มีโค้ด Codelab เวอร์ชันก่อนและหลัง โค้ดแล็บจะเริ่มต้นด้วยเทมเพลตโปรเจ็กต์ที่ว่างเปล่าและสร้างขึ้นจนถึงสถานะที่เสร็จสมบูรณ์ คุณสามารถใช้โปรเจ็กต์ที่เสร็จสมบูรณ์ในที่เก็บเป็นข้อมูลอ้างอิงได้หากติดขัด

โคลนที่เก็บหรือดาวน์โหลดโค้ด

ไปที่ไดเรกทอรีที่คุณต้องการจัดเก็บ Codelab

จากนั้นโคลนที่เก็บหรือดาวน์โหลดโค้ด

git clone https://github.com/googlemaps-samples/codelab-navigation-101-ios-swift

หากไม่ได้ติดตั้ง Git ให้คลิกปุ่มนี้เพื่อรับโค้ด

ที่เก็บมีโค้ดเริ่มต้นบางส่วนในโฟลเดอร์ Starter เพื่อช่วยให้คุณทำตาม Codelab นี้ได้ง่ายขึ้น นอกจากนี้ ยังมีSolutionโปรเจ็กต์ที่เสร็จสมบูรณ์แล้วในกรณีที่คุณต้องการข้ามไปข้างหน้าหรือตรวจสอบความคืบหน้าได้ทุกเมื่อ หากต้องการใช้โปรเจ็กต์โซลูชัน คุณจะต้องทำตามวิธีการ "ติดตั้งโดยใช้ Cocoapods" ด้านล่าง แล้วเรียกใช้คำสั่ง "pod update" จากโฟลเดอร์ solution/Navigation SDK Codelab

เมื่อโคลนที่เก็บในเครื่องแล้ว ให้ใช้ XCode เพื่อเปิดโฟลเดอร์ Starter เป็นโปรเจ็กต์ที่มีอยู่ ตรวจสอบว่าโปรเจ็กต์สร้างและเรียกใช้ได้

เชื่อมต่ออุปกรณ์หรือตั้งค่าโปรแกรมจำลอง XCode

4. เพิ่ม Navigation SDK ลงในแอป

คุณผสานรวม Navigation SDK เข้ากับโปรเจ็กต์ XCode ได้ 3 วิธี โดย Codelab นี้ใช้ CocoaPods ดูรายละเอียดเกี่ยวกับวิธีผสานรวมโดยใช้ Swift Package Manager หรือติดตั้งด้วยตนเองโดยการดาวน์โหลด SDK ได้ที่สร้างโปรเจ็กต์ Xcode และติดตั้ง Navigation SDK ในเอกสารประกอบของ Navigation SDK

ติดตั้งโดยใช้ Cocoapods

หากยังไม่มีเครื่องมือ CocoaPods ให้ติดตั้งใน macOS โดยเรียกใช้คำสั่งต่อไปนี้จากเทอร์มินัล โปรดดูรายละเอียดในคู่มือการเริ่มต้นใช้งาน CocoaPods

sudo gem install cocoapods

สร้างไฟล์ใหม่ชื่อ Podfile ในโฟลเดอร์โปรเจ็กต์ภายในโฟลเดอร์ Codelab ของ Starter/Navigation SDK (ใน XCode ให้ไปที่ File > New > File > Other > Empty แล้วบันทึกเป็น "Podfile")

เพิ่มเนื้อหาต่อไปนี้ลงใน Podfile

source 'https://github.com/CocoaPods/Specs.git'

platform :ios, '15.0'

target 'Navigation SDK Codelab' do
  pod 'GoogleNavigation', '9.1.1'
end

ประหยัด Podfile

เปิดเทอร์มินัลและเปลี่ยนไดเรกทอรีไปยังตำแหน่งที่คุณบันทึก Podfile (ควรเป็นโฟลเดอร์ "starter/Navigation SDK Codelab" ในที่เก็บ Codelab)

cd "<path-to-starter-project-folder>/Navigation SDK Codelab"

เรียกใช้คำสั่ง pod install ซึ่งจะติดตั้ง API ที่ระบุใน Podfile พร้อมกับการอ้างอิง

pod install

ปิด Xcode แล้วเปิดไฟล์ .xcworkspace ของโปรเจ็กต์เพื่อเปิด Xcode ตั้งแต่นี้เป็นต้นไป คุณต้องใช้ไฟล์ .xcworkspace เพื่อเปิดโปรเจ็กต์

ตรวจสอบว่าได้เพิ่มไดเรกทอรี Pods ลงในโครงสร้างโปรเจ็กต์แล้ว และมี Pods "GoogleMaps" และ "GoogleNavigation"

6e81772ee067d452.png

เพิ่มคีย์ API

เพิ่มคีย์ API ลงใน AppDelegate.swift ดังนี้

  1. เพิ่มคำสั่งนำเข้าต่อไปนี้
import GoogleMaps
import GoogleNavigation
  1. เพิ่มโค้ดต่อไปนี้ในเมธอด application(_:didFinishLaunchingWithOptions:)
GMSServices.provideAPIKey("YOUR_API_KEY")

แทนที่ "YOUR_API_KEY" ด้วยคีย์ API ที่คุณสร้างในขั้นตอนก่อนหน้า

สร้างโปรเจ็กต์และแก้ไขข้อผิดพลาด

5. กำหนดค่าสิทธิ์ของแอป

Navigation SDK อาศัยสัญญาณ GPS เพื่อระบุตำแหน่งที่สแนปกับถนนและคำแนะนำแบบเลี้ยวต่อเลี้ยว ดังนั้นแอปของคุณจะต้องขอให้ผู้ใช้ให้สิทธิ์เข้าถึงข้อมูลตำแหน่งที่แน่นอน

โดยคุณจะต้องเพิ่มพร็อพเพอร์ตี้บางอย่างลงใน Info.plist ของแอปใน Xcode เพิ่มโค้ดบางอย่างลงในแอปเพื่อขอสิทธิ์จากผู้ใช้ในขณะรันไทม์ และจัดการข้อผิดพลาดต่างๆ เช่น ไม่ได้รับสิทธิ์หรือตำแหน่งไม่พร้อมใช้งาน

เปิด Info.plist ใน Xcode ซึ่งควรมีหน้าตาเช่นนี้

6532a85bd9ac8fb4.png

ขอสิทธิ์เข้าถึงตำแหน่งที่แน่นอน

คุณเพิ่มค่าใหม่ได้โดยวางเคอร์เซอร์ของเมาส์เหนือแถว "รายการพร็อพเพอร์ตี้ข้อมูล" จนกว่าจะเห็นไอคอน "+" ปรากฏขึ้น คลิก "+" เพื่อดูกล่องโต้ตอบที่มีชื่อพร็อพเพอร์ตี้ที่แนะนํา แต่โปรดทราบว่าคุณยังเพิ่มพร็อพเพอร์ตี้ด้วยตนเองได้ด้วย

เพิ่มพร็อพเพอร์ตี้และค่าต่อไปนี้ลงใน Info.plist

พร็อพเพอร์ตี้

ค่า

ความเป็นส่วนตัว - คำอธิบายการใช้งานตำแหน่ง "ตลอดเวลา" และ "เมื่อใช้งาน"

"แอปนี้ต้องใช้ตำแหน่งของอุปกรณ์เพื่อแสดงการนำทางแบบเลี้ยวต่อเลี้ยว"

ความเป็นส่วนตัว - คำอธิบายการใช้งานตำแหน่งเมื่อใช้งาน

"แอปนี้ต้องใช้ตำแหน่งของอุปกรณ์เพื่อแสดงการนำทางแบบเลี้ยวต่อเลี้ยว"

allowsBackgroundLocationUpdates

ใช่

ขอสิทธิ์เข้าถึงตำแหน่งในเบื้องหลัง

เพิ่มพร็อพเพอร์ตี้และค่าต่อไปนี้ลงใน Info.plist

UIBackgroundModes > เพิ่มแถว > Item 0: App registers for location updates (เลือกค่านี้จากรายการแบบเลื่อนลงของคำแนะนำ)

เมื่อเสร็จแล้ว Info.plist ควรมีลักษณะดังนี้

3b0c49018451d0ff.png

ขอสิทธิ์เข้าถึงตำแหน่งขณะรันไทม์

เพิ่มคำสั่งนำเข้าต่อไปนี้ลงใน ViewController.swift

import GoogleNavigation

เพิ่มการประกาศต่อไปนี้ลงในคลาส ViewController

var locationManager: CLLocationManager!

เพิ่มการลบล้างวิธีการสำหรับ loadView() แล้วเรียกใช้ locationManager.requestAlwaysAuthorization() ดังนี้

override func loadView() {
        locationManager = CLLocationManager()
        locationManager.requestAlwaysAuthorization()

ตอนนี้แอปจะขอตำแหน่งจากผู้ใช้และทำให้แอปของคุณเข้าถึงได้หากผู้ใช้ให้สิทธิ์

ขอสิทธิ์เพื่อแสดงการแจ้งเตือน

เพิ่มโค้ดต่อไปนี้ลงใน loadView() เพื่อขอสิทธิ์จากผู้ใช้ในการแสดงการแจ้งเตือน ซึ่งจำเป็นต่อการแสดงวิธีการเลี้ยว

UNUserNotificationCenter.current().requestAuthorization(options: [.alert]) {
        granted, error in
        // Handle denied authorization to display notifications.
          if !granted || error != nil {
              print("User rejected request to display notifications.")
          }
        }

สร้างและเรียกใช้แอป แล้วตรวจสอบว่าระบบแจ้งให้คุณแชร์ตำแหน่งและเปิดใช้การแจ้งเตือน

ad5f665a21170c49.png

6. เพิ่มอินเทอร์เฟซผู้ใช้สำหรับการนำทาง

ในขั้นตอนนี้ คุณจะเพิ่มแผนที่และกำหนดค่าให้แสดงตำแหน่ง จากนั้นคุณจะแสดงกล่องโต้ตอบที่มีข้อกำหนดในการใช้งาน Navigation SDK ต่อผู้ใช้

เพิ่มมุมมองแผนที่ลงในแอป

เพิ่มบรรทัดนี้เพื่อประกาศตัวแปร GMSMapView ใน ViewController

var mapView: GMSMapView!

เพิ่มโค้ดต่อไปนี้ลงใน loadView() ใน Viewcontroller.swift เพื่อเริ่มต้นแผนที่

let camera = GMSCameraPosition.camera(withLatitude: 51.483174, longitude: -0.177369, zoom: 14)
let options = GMSMapViewOptions()
options.camera = camera
options.frame = .zero
        
mapView = GMSMapView(options: options)
view = mapView

สร้างและเรียกใช้แอป คุณควรเห็นแผนที่ที่อยู่ตรงกลางทางตะวันตกเฉียงใต้ของลอนดอน

1d46ce5c0851cae3.png

แสดงกล่องโต้ตอบข้อกำหนดในการใช้งานผลิตภัณฑ์ Navigation SDK

เพิ่มโค้ดต่อไปนี้ลงใน ViewController.swift ในเมธอด loadView() เดียวกันกับโค้ดก่อนหน้า ซึ่งจะแสดงข้อกำหนดในการใช้งานสำหรับผู้ใช้ปลายทางของ Navigation SDK หากไม่ยอมรับ ระบบจะไม่เปิดใช้การนำทาง

// Show the terms and conditions.
let companyName = "Navigation SDK Codelab"
GMSNavigationServices.showTermsAndConditionsDialogIfNeeded(withCompanyName: companyName) { termsAccepted in
  if termsAccepted {
    // Enable navigation if the user accepts the terms.
    self.mapView.isNavigationEnabled = true
    // Request authorization for alert notifications which deliver guidance instructions
    // in the background.
  } else {
    // Handle the case when the user rejects the terms and conditions.
  }
}

สร้างและเรียกใช้แอปเพื่อดูกล่องโต้ตอบ

29f17ae5b4c07c9f.png

7. เพิ่ม Listener สำหรับเหตุการณ์การนำทางที่สำคัญ

ขั้นตอนนี้จะแสดงวิธีตั้งค่า Listener สำหรับเหตุการณ์สำคัญ เช่น การมาถึงจุดหมาย หรือการเปลี่ยนเส้นทางของคนขับ

หากต้องการฟังเหตุการณ์เหล่านี้ ตัวควบคุมมุมมองต้องใช้โปรโตคอล GMSNavigatorListener

เพิ่มโปรโตคอลนี้ลงในคำจำกัดความของคลาสใน ViewController.swift

class ViewController: UIViewController,
                      GMSNavigatorListener {

ตอนนี้ให้เพิ่มบรรทัดโค้ดเพื่อตั้งค่า Listener ใน loadView():

// Add a listener for GMSNavigator.
mapView.navigator?.add(self)

สุดท้าย ให้เพิ่ม 2 วิธีลงในคลาสเพื่อจัดการเหตุการณ์ที่เกิดขึ้น

// Listener to handle arrival events.
func navigator(_ navigator: GMSNavigator, didArriveAt waypoint: GMSNavigationWaypoint) {
  print("You have arrived at: \(waypoint.title)")
}

// Listener for route change events.
func navigatorDidChangeRoute(_ navigator: GMSNavigator) {
  print("The route has changed.")
}

8. กำหนดจุดหมายและเริ่มการนำทาง

ส่วนนี้จะสอนวิธีตั้งค่าจุดหมายและเริ่มคำแนะนำการนำทาง

สร้างฟังก์ชันใหม่สำหรับตรรกะการนำทาง

ก่อนอื่น ให้เพิ่มฟังก์ชันใหม่ชื่อ startNav() ใน ViewController ซึ่งจะมีตรรกะในการตั้งค่าปลายทางและเริ่มการนำทาง

// Create a route and start guidance.
@objc func startNav() {
}

สร้าง Waypoint สำหรับปลายทาง

จากนั้นสร้างอาร์เรย์ของปลายทางที่มีจุดอ้างอิงเดียว

// Create a route and start guidance.
@objc func startNav() {
  var destinations = [GMSNavigationWaypoint]()
  destinations.append(
    GMSNavigationWaypoint.init(
      placeID: "ChIJH-tBOc4EdkgRJ8aJ8P1CUxo",
      title: "Trafalgar Square")!)
}

โทรหา setDestinations()และจัดการการตอบกลับ

จากนั้นเรียกใช้ setDestinations และจัดการ GMSRouteStatus ที่ส่งคืน

หาก GMSRouteStatus เป็น "ตกลง" ให้เริ่มคำแนะนำโดยตั้งค่า isGuidanceActive=true ในออบเจ็กต์ navigator ของ mapView หรือพิมพ์ใบแจ้งยอดเพื่อแสดงว่ามีข้อผิดพลาด

หากค่า GMSRouteStatus ที่แสดงผลเป็น "OK" ให้เริ่มจำลองการขับรถไปตามเส้นทางโดยเรียกใช้ mapView.locationSimulator.simulateLocationsAlongExistingRoute()

// Create a route and start guidance.
@objc func startNav() {
  var destinations = [GMSNavigationWaypoint]()
    destinations.append(
      GMSNavigationWaypoint.init(
        placeID: "ChIJH-tBOc4EdkgRJ8aJ8P1CUxo",
          title: "Trafalgar Square")!)
      
  mapView.navigator?.setDestinations(
    destinations
  ) { routeStatus in
    guard routeStatus == .OK else {
      print("Handle route statuses that are not OK.")
      return
    }
    //If routeStatus is OK, start guidance.
    self.mapView.navigator?.isGuidanceActive = true
    //start simulating driving along the route. self.mapView.locationSimulator?.simulateLocationsAlongExistingRoute()
    self.mapView.cameraMode = .following
  }
}

จัดการสถานะข้อผิดพลาดที่พบบ่อย

การจัดการข้อผิดพลาด GMSRouteStatus อย่างชัดเจนยิ่งขึ้นจะมีประโยชน์ โดยเฉพาะเมื่อแก้ไขข้อบกพร่องเบื้องต้นของแอปใหม่ ตัวอย่างเช่น คุณอาจพบว่าได้รับสิทธิ์เข้าถึงตำแหน่ง, คีย์ API หรือข้อผิดพลาด "ไม่พบเส้นทาง" บ่อยขึ้นในช่วงแรกเนื่องจากการตั้งค่าการแก้ไขข้อบกพร่อง ดังนั้นการจัดการสถานะข้อผิดพลาดเหล่านี้จึงอาจมีประโยชน์

เพิ่มโค้ดที่จัดการกรณีเฉพาะเหล่านี้และพิมพ์ข้อความไปยังคอนโซล

mapView.navigator?.setDestinations(
  destinations
) { routeStatus in
    guard routeStatus == .OK else {
      print("Handle route statuses that are not OK.")
      switch routeStatus {
       case .locationUnavailable:
        print("Location unavailable.") //check permissions
      case .noRouteFound:
        print("No route found.") //check start location and destination
      case .waypointError:
        print("Waypoint error") //check Place ID
      default:
        print("Not sure what happened")
      }
    return
  }

เพิ่มปุ่มเพื่อเริ่มคำแนะนำในการนำทาง

สุดท้าย ให้เพิ่มปุ่มลงใน UI และเชื่อมต่อปุ่มกับเมธอด startNav สร้างเมธอดชื่อ makeButton() ด้วยโค้ดต่อไปนี้ เรียกใช้ฟังก์ชัน makeButton() จาก loadView()

// Add a button to the view.
func makeButton() {
  // A button to 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)
}

สร้างและเรียกใช้แอป

หมายเหตุ: การเรียกใช้โค้ดใน

startNav()

จะโทรหา

setDestinations()

ซึ่งจะมีการเรียกเก็บเงินหลังจากใช้ปลายทาง 1,000 แห่งแรก ดูข้อมูลเพิ่มเติมได้ที่การใช้งานและการเรียกเก็บเงิน

9. ยินดีด้วย

เก่งมาก คุณมาถึงจุดหมายแล้ว

7a69dcb75c904d7.png

คุณได้สร้างแอปง่ายๆ ที่ให้คำแนะนำการนำทางแบบเลี้ยวต่อเลี้ยวไปยังจุดหมายโดยใช้ Navigation SDK ของ Google Maps Platform

คุณได้กำหนดค่าสิทธิ์ของแอปและกล่องโต้ตอบข้อกำหนดของผู้ใช้ปลายทางของ Navigation SDK รวมถึงระบุปลายทางโดยใช้รหัสสถานที่ คุณได้จัดการสถานะต่างๆ ที่สำเร็จและเกิดข้อผิดพลาดในแอปแล้ว

10. สู่ขั้นต่อไป

หากต้องการพัฒนาแอปให้ดียิ่งขึ้น โปรดดูหัวข้อต่อไปนี้เพื่อรับแรงบันดาลใจ

  • ฟังเหตุการณ์การนำทางเพิ่มเติม เพิ่มโค้ดเพื่อแสดงข้อความหากเวลาหรือระยะทางที่เหลือเกินเกณฑ์
  • ปรับแต่งอินเทอร์เฟซการนำทาง
  • หากต้องการความท้าทายที่มากขึ้น ลองเพิ่มเครื่องมือเลือกสถานที่ของ Places API เพื่อให้ผู้ใช้ตั้งค่าปลายทางได้ เคล็ดลับ: แอปเดโมของ Navigation SDK มีการใช้งานตัวอย่าง เรียกใช้ pod try GoogleNavigation ในโฟลเดอร์โปรเจ็กต์เพื่อดูโค้ด