[SwiftUI] UberClone: RouteView

Junyoung ParkΒ·2022λ…„ 11μ›” 19일
0

SwiftUI

λͺ©λ‘ 보기
115/136
post-thumbnail
post-custom-banner

πŸ”΄ Let's Build UBER with SwiftUI | iOS 16 & Xcode 14

UberClone: RouteView

κ΅¬ν˜„ λͺ©ν‘œ

μ—…λ‘œλ“œμ€‘..

  • λ„μ°©μ§€λ‘œ μ΄μ–΄μ§€λŠ” UI κ΅¬ν˜„

κ΅¬ν˜„ νƒœμŠ€ν¬

  • μΆœλ°œμ§€μ—μ„œ λ„μ°©μ§€κΉŒμ§€μ˜ 경둜 λ°›μ•„μ˜€κΈ°
  • 맡뷰 λ‚΄ ν•΄λ‹Ή 경둜 UI 그리기

핡심 μ½”λ“œ

var userLocationCoordinate: CLLocationCoordinate2D?

...

 func mapView(_ mapView: MKMapView, didUpdate userLocation: MKUserLocation) {
            userLocationCoordinate = userLocation.coordinate
            setRegion(with: userLocation.coordinate)
        }

졜초 μœ μ € 정보λ₯Ό 톡해 μ‹€ν–‰λ˜λŠ” 맡뷰의 델리게이트 ν•¨μˆ˜ μ†μ—μ„œ ν•΄λ‹Ή 값을 μ „μ—­μ—μ„œ μ ‘κ·Ό κ°€λŠ₯ν•˜λ„λ‘ 담아두기

private func getDestinationRoute(from start: CLLocationCoordinate2D, to destination: CLLocationCoordinate2D, completion: @escaping(Result<MKRoute, Error>) -> Void) {
            let start = MKPlacemark(coordinate: start)
            let destination = MKPlacemark(coordinate: destination)
            let request = MKDirections.Request()
            request.source = MKMapItem(placemark: start)
            request.destination = MKMapItem(placemark: destination)
            let direction = MKDirections(request: request)
            direction.calculate { response, error in
                guard
                    error == nil,
                    let route = response?.routes.first else {
                    if let error = error {
                        completion(.failure(error))
                    } else {
                        completion(.failure(URLError(.badURL)))
                    }
                    return
                }
                completion(.success(route))
            }
        }
  • μΆœλ°œμ§€μ™€ 도착지가 μ’Œν‘œκ°’μœΌλ‘œ μ£Όμ–΄μ§ˆ λ•Œ MKDirections의 λ©”μ†Œλ“œ calculateλ₯Ό 톡해 경둜λ₯Ό λ¦¬ν„΄ν•˜λŠ” ν•Έλ“€λŸ¬ ν•¨μˆ˜
func configurePolyline(with destinationCoordinate: CLLocationCoordinate2D) {
            guard let userLocationCoordinate = userLocationCoordinate else { return }
            getDestinationRoute(from: userLocationCoordinate, to: destinationCoordinate) { [weak self] result in
                switch result {
                case .success(let route):
                    self?.parent.mapView.addOverlay(route.polyline)
                case .failure(let error): print(error.localizedDescription)
                }
            }
        }
  • 도착지가 μ£Όμ–΄μ§ˆ λ•Œ μ „μ—­μ—μ„œ μ ‘κ·Ό κ°€λŠ₯ν–ˆλ˜ ν˜„ μ‹œμ μ˜ μœ μ € 정보(즉 μΆœλ°œμ§€μ˜ μ’Œν‘œκ°’)을 톡해 경둜λ₯Ό λ°›μ•„μ˜΄
  • 경둜λ₯Ό 지도 상에 ν‘œν˜„ν•˜κΈ° μœ„ν•΄ addOverlayλ₯Ό 톡해 μΆ”κ°€
func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
            let polyline = MKPolylineRenderer(overlay: overlay)
            polyline.strokeColor = .systemBlue
            polyline.lineWidth = 6
            return polyline
        }
  • 맡뷰 λ‚΄ μ˜€λ²„λ ˆμ΄κ°€ 좔가될 λ•Œ μ‹€ν–‰λ˜λŠ” 델리게이트 ν•¨μˆ˜
  • 색깔 및 κ΅΅κΈ° 등을 미리 μ„€μ • κ°€λŠ₯
func updateUIView(_ uiView: UIViewType, context: Context) {
        if let selectedLocation = viewModel.selectedLocation {
            context.coordinator.addAndSelectAnnotation(with: selectedLocation)
            context.coordinator.configurePolyline(with: selectedLocation)
        }
    }
  • UIViewRepresentable의 λ©”μ†Œλ“œ 쀑 λ·°λ₯Ό μ—…λ°μ΄νŠΈν•˜λŠ” μ½”λ“œ λ‚΄μ—μ„œ λ·° λͺ¨λΈμ˜ selectedLocation을 κ΄€μ°°ν•œ 이후 ν•΄λ‹Ή μ’Œν‘œλ‘œμ˜ 경둜λ₯Ό 받아와 선을 κ·Έλ¦¬λŠ” 델리게이트 ν•¨μˆ˜ 호좜

κ΅¬ν˜„ ν™”λ©΄

μ—…λ‘œλ“œμ€‘..

profile
JUST DO IT
post-custom-banner

0개의 λŒ“κΈ€