I’m attempting to create a mapbox map and cargo a listing of nations from a csv file. The annotations are added from this line which works. Nevertheless, I solely want this operate to execute as soon as or it’ll causes efficiency challenge. Irrespective of I alter the road to a different place, it would not work.
I’m new to Swift and any assist is way appreciated.
func updateUIView(_ uiView: MapboxMaps.MapView, context: Context) {
addCountryAnnotations(to: uiView, context: context)
}
That is my full code.
//
// ContentView.swift
//
import SwiftUI
import MapboxMaps
import CoreLocation
import FlagKit
struct ContentView: View {
@StateObject personal var viewModel = CountryViewModel()
@StateObject personal var locationManager = LocationManager()
@State personal var isPanelExpanded = false
@State personal var selectedCountry: Nation?
@State personal var countryInfo: String = ""
var physique: some View {
ZStack {
MapViewRepresentable(international locations: viewModel.international locations, userLocation: locationManager.location, onCountryTapped: { nation, data in
selectedCountry = nation
countryInfo = data
isPanelExpanded = true
})
.ignoresSafeArea()
.onAppear {
viewModel.loadCountries()
locationManager.requestLocation()
}
VStack {
Spacer()
BottomPanelView(isExpanded: $isPanelExpanded, nation: $selectedCountry, countryInfo: $countryInfo)
.body(top: isPanelExpanded ? 300 : 100)
.transition(.transfer(edge: .backside))
}
}
}
}
struct MapViewRepresentable: UIViewRepresentable {
let international locations: [Country]
let userLocation: CLLocationCoordinate2D?
let onCountryTapped: (Nation, String) -> Void
personal func fetchCountryInfo(for nation: Nation, completion: @escaping (Outcome) -> Void) {
let countryName = nation.identify.replacingOccurrences(of: " ", with: "_")
let urlString = "https://en.wikipedia.org/api/rest_v1/web page/abstract/(countryName)"
guard let url = URL(string: urlString) else {
completion(.failure(NSError(area: "Invalid URL", code: 0, userInfo: nil)))
return
}
let process = URLSession.shared.dataTask(with: url) { information, response, error in
if let error = error {
completion(.failure(error))
return
}
guard let information = information else {
completion(.failure(NSError(area: "No information", code: 0, userInfo: nil)))
return
}
do {
if let json = attempt JSONSerialization.jsonObject(with: information, choices: []) as? [String: Any],
let extract = json["extract"] as? String {
print("Fetched content material: (extract)") // Debugging print assertion
completion(.success(extract))
} else {
completion(.failure(NSError(area: "Invalid JSON", code: 0, userInfo: nil)))
}
} catch {
completion(.failure(error))
}
}
process.resume()
}
static let defaultLocation = CLLocationCoordinate2D(latitude: 22.3193, longitude: 114.1694)
func makeUIView(context: Context) -> MapboxMaps.MapView {
let choices = MapInitOptions(cameraOptions: CameraOptions(heart: userLocation ?? MapViewRepresentable.defaultLocation, zoom: 10))
let mapView = MapboxMaps.MapView(body: .zero, mapInitOptions: choices)
mapView.gestures.delegate = context.coordinator
context.coordinator.mapView = mapView
return mapView
}
func updateUIView(_ uiView: MapboxMaps.MapView, context: Context) {
addCountryAnnotations(to: uiView, context: context)
}
personal func addCountryAnnotations(to mapView: MapboxMaps.MapView, context: Context) {
var annotations: [PointAnnotation] = []
for nation in international locations {
var annotation = PointAnnotation(coordinate: nation.coordinate)
if let flagImage = nation.flagImage {
annotation.picture = .init(picture: flagImage.resized(to: CGSize(width: 30, top: 20)), identify: nation.code)
}
annotation.iconAnchor = .backside
annotations.append(annotation)
}
let annotationManager = mapView.annotations.makePointAnnotationManager()
annotationManager.annotations = annotations
annotationManager.delegate = context.coordinator
}
func makeCoordinator() -> Coordinator {
Coordinator(self)
}
class Coordinator: NSObject, AnnotationInteractionDelegate, GestureManagerDelegate {
var dad or mum: MapViewRepresentable
var mapView: MapboxMaps.MapView?
init(_ dad or mum: MapViewRepresentable) {
self.dad or mum = dad or mum
}
func annotationManager(_ supervisor: AnnotationManager, didDetectTappedAnnotations annotations: [Annotation]) {
guard let annotation = annotations.first as? PointAnnotation, let countryName = annotation.textField else { return }
if let nation = dad or mum.international locations.first(the place: { $0.identify == countryName }) {
dad or mum.fetchCountryInfo(for: nation) { end in
swap consequence {
case .success(let data):
DispatchQueue.most important.async {
self.dad or mum.onCountryTapped(nation, data)
}
case .failure(let error):
print("Did not fetch nation data: (error.localizedDescription)")
}
}
flyToCountry(nation)
}
}
personal func flyToCountry(_ nation: Nation) {
guard let mapView = mapView else { return }
let cameraOptions = CameraOptions(heart: nation.coordinate, zoom: 10, bearing: 0, pitch: 0)
mapView.digital camera.fly(to: cameraOptions, length: 2.0)
}
// Implement required strategies for GestureManagerDelegate
func gestureManager(_ gestureManager: GestureManager, didBegin gestureType: GestureType) {}
func gestureManager(_ gestureManager: GestureManager, didEnd gestureType: GestureType, willAnimate: Bool) {}
func gestureManager(_ gestureManager: GestureManager, didEndAnimatingFor gestureType: GestureType) {}
}
}
class LocationManager: NSObject, ObservableObject, CLLocationManagerDelegate {
personal let locationManager = CLLocationManager()
@Printed var location: CLLocationCoordinate2D?
override init() {
tremendous.init()
locationManager.delegate = self
}
func requestLocation() {
locationManager.requestWhenInUseAuthorization()
locationManager.requestLocation()
}
func locationManager(_ supervisor: CLLocationManager, didUpdateLocations areas: [CLLocation]) {
location = areas.first?.coordinate
}
func locationManager(_ supervisor: CLLocationManager, didFailWithError error: Error) {
print("Did not get consumer location: (error.localizedDescription)")
}
}
extension UIImage {
func resized(to measurement: CGSize) -> UIImage {
UIGraphicsBeginImageContextWithOptions(measurement, false, 0.0)
draw(in: CGRect(origin: .zero, measurement: measurement))
let resizedImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return resizedImage!
}
}
I adopted the official documentations of right here, nonetheless, it would not give instance on learn how to work together from organising the map and nonetheless utilizing UIKit. I assume that is fairly outdated.
https://docs.mapbox.com/ios/maps/guides/markers-and-annotations/annotations/