๐ด Let's Build UBER with SwiftUI | iOS 16 & Xcode 14
UberClone: MapView
๊ตฌํ ๋ชฉํ
๊ตฌํ ํ์คํฌ
- UIKit ์ปดํฌ๋ํธ์ SwiftUI ๋ด ์ฌ์ฉ์ ์ํ
UIViewRepresentable
- ํ๋ทฐ ๋ด ์ฌ์ฉ๋๋ ๋ก์ผ์ด์
๋งค๋์
ํต์ฌ ์ฝ๋
import Foundation
import CoreLocation
class LocationManager: NSObject, ObservableObject {
private let locationManager = CLLocationManager()
override init() {
super.init()
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.requestWhenInUseAuthorization()
locationManager.startUpdatingLocation()
}
}
extension LocationManager: CLLocationManagerDelegate {
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
guard !locations.isEmpty else { return }
locationManager.stopUpdatingLocation()
}
}
- ๋งต๋ทฐ ๋ด์์ ์ฌ์ฉ๋๋
ObservableObject
๋ก ์ ์ธ๋๋ ๋ก์ผ์ด์
๋งค๋์
CLLocationManagerDelegate
ํจ์๋ฅผ ์ฌ์ฉ, ์ ์ ์ ๋ณด์ ๋ฐ๋ผ ์ง๋๋ฅผ ์
๋ฐ์ดํธํ ๋ค ์
๋ฐ์ดํธ๋ ์ดํ ๊ณง๋ฐ๋ก ์
๋ฐ์ดํธ ์ค์ง
import SwiftUI
import MapKit
struct UberMapViewRepresentable: UIViewRepresentable {
let mapView = MKMapView()
let locationManager = LocationManager()
func makeCoordinator() -> MapCoordinator {
return MapCoordinator(parent: self)
}
func makeUIView(context: Context) -> some UIView {
mapView.delegate = context.coordinator
mapView.isRotateEnabled = false
mapView.showsUserLocation = true
mapView.userTrackingMode = .follow
return mapView
}
func updateUIView(_ uiView: UIViewType, context: Context) {
}
}
- SwiftUI์์ UIKit ์ปดํฌ๋ํธ๋ฅผ ์ฌ์ฉํ๊ธฐ ์ํ
UIViewRepresentable
์ ์ค์ํ๋ ํด๋์ค ์ ์ธ
- ํด๋น ํ๋กํ ์ฝ์ ๋ฐ๋ฅด๊ธฐ ์ํ ํจ์ ์ ์ธ์ ํตํด ๋ธ๋ฆฌ๊ฒ์ดํธ์ ์กฐ์จํ๋
makeCoordinator
, ์ฌ์ฉํ ์ปค์คํ
๋ทฐ ํด๋์ค๋ฅผ ๋์ง๋ makeUIView
ํจ์ ์ ์ฉ
- ํด๋์ค ๋ด ์ปค์คํ
์ผ๋ก ์ ์ธ๋๋ ๊ณณ(๋งต๋ทฐ, ๋ก์ผ์ด์
๋งค๋์ ๋ฑ)์ ๋ธ๋ฆฌ๊ฒ์ดํธ ํจ์์์๋ ์ ๊ทผ ๊ฐ๋ฅ
- ์ฆ ํ์ฌ UIView ์
์ฅ์์๋ ์ฌ์ฉํ๊ณ ์ ํ๋ ํน์ ํ ๋ทฐ์ ๋ธ๋ฆฌ๊ฒ์ดํธ ํจ์๋ ์์ง ๋ชปํ๊ณ ,
Coordinator
์ ๊ฒฝ์ ํด์๋ง ์ฌ์ฉ ๊ฐ๋ฅ(ํ์ฌ ๋งต๋ทฐ์ ๋ธ๋ฆฌ๊ฒ์ดํธ์ ์ปจํ
์คํธ์ coordinator
๋ฅผ ๋๊ธฐ๊ธฐ ๋๋ฌธ)
extension UberMapViewRepresentable {
class MapCoordinator: NSObject, MKMapViewDelegate {
let parent: UberMapViewRepresentable
init(parent: UberMapViewRepresentable) {
self.parent = parent
super.init()
}
func mapView(_ mapView: MKMapView, didUpdate userLocation: MKUserLocation) {
let region = MKCoordinateRegion(center: .init(latitude: userLocation.coordinate.latitude, longitude: userLocation.coordinate.longitude), span: .init(latitudeDelta: 0.05, longitudeDelta: 0.05))
parent.mapView.setRegion(region, animated: true)
}
}
}
- ์ปค์คํ
๋ทฐ์์ ์ ์ธ๋๋
Coordinator
ํด๋์ค
- ์์ ์ปค์คํ
๋ทฐ๋ฅผ
self
๋ก ์ฃผ๊ธฐ ๋๋ฌธ์ ๋ธ๋ฆฌ๊ฒ์ดํธ ํจ์ ์ฌ์ฉ ๊ฐ๋ฅ
- ํ์ฌ ์ฌ์ฉ ์ค์ธ ๋งตํท์ ๋ธ๋ฆฌ๊ฒ์ดํธ ํจ์๋ ์ ์ ์์นํ ๊ฐ์ ํตํด ๋งต๋ทฐ์ ์ง์ญ์ ์ธํ
ํ๋ ํจ์
import SwiftUI
struct HomeView: View {
var body: some View {
UberMapViewRepresentable()
.ignoresSafeArea()
}
}
- ์์ ๋งตํท ์์ฒด๋ฅผ ์ ์ฒด ์ง๋๋ก ์ฌ๋ฆฌ๋ ์ฝ๋
๊ตฌํ ํ๋ฉด