How to Integrate Mapbox Sdk with Swiftui

How to integrate Mapbox SDK with SwiftUI

This is a working sample on how you can integrate the MGLMapView with SwiftUI.

When using UIViewRepresentable you have to implement two delegates: makeUIView that will return your view (in this case MGLMapView) and updateUIView which will receive the same view type as the one returned in makeUIView (again MGLMapView).

You can use this to experiment.

Also I recommend you get familiar with the React architecture to understand better the SwiftUI approach.

You can improve this sample by making ContentView receive a styleURL, and trying different styles in the preview.

import Mapbox
import SwiftUI

struct ContentView : View {
var body: some View {

MapboxViewRepresentation(MGLStyle.streetsStyleURL)

}
}

#if DEBUG
struct ContentView_Previews : PreviewProvider {
static var previews: some View {
ContentView()
}
}
#endif

struct MapboxViewRepresentation : UIViewRepresentable {

let styleURL: URL

init(_ styleURL: URL) {
self.styleURL = styleURL
}

func makeUIView(context: UIViewRepresentableContext<MapboxViewRepresentation>) -> MGLMapView {
let mapView = MGLMapView(frame: .zero, styleURL: styleURL)

return mapView
}

func updateUIView(_ uiView: MGLMapView, context: UIViewRepresentableContext<MapboxViewRepresentation>) {

}

}

UPDATE: Here is the official guide on how to integrate Mapbox with SwiftUI https://docs.mapbox.com/help/tutorials/ios-swiftui/

Mapbox autocomplete feature on iOS SwiftUI

Apparently for SwiftUI, you'll have to build the Autocomplete search feature on your own by using Mapbox Geocoding API. I made something simple, as shown below.

import SwiftUI
import Alamofire

struct AutocompleteSheet: View {

@State var searchText = ""
@State var SearchResults:[data]? = nil

var body: some View {

ScrollView {

HStack {
TextField(" Search locations", text: $searchText)
}
.onChange(of: searchText, perform: { value in
AutocompleteAPI()
})
}

if SearchResults != nil {

ForEach(0..<SearchResults!.count, id: \.self) { index in

HStack {
Button(action: {
print("which location: \(index)")
}) {

Image(systemName: "mappin.and.ellipse")
.foregroundColor(Color(.systemGray2))

Text("\(SearchResults![index].name)")
}
}
}
}
}
}

func AutocompleteAPI() -> Void {

let parameters:Parameters = [:]

APIClient.Autocomplete(query : searchText, completion:{(result) in
switch(result){

case .success(let Details):

print(Details)

if (Details.meta.statusCode == 200) {

print("Successful")
SearchResults = Details.data
}
else{

print("Fail")
}

case .failure(let error):
print("ERROR",error)
}
})
}
}

Mapbox iOS Navigation SDK Not Working With SwiftUI

For this case it should be used UIViewControllerRepresentable, like below

struct NavView: UIViewControllerRepresentable {

func makeUIViewController(context: Context) -> NavigationViewController {
var viewController: NavigationViewController

// Define two waypoints to travel between
let origin = Waypoint(coordinate: CLLocationCoordinate2D(latitude: 38.9131752, longitude: -77.0324047), name: "Mapbox")
let destination = Waypoint(coordinate: CLLocationCoordinate2D(latitude: 38.8977, longitude: -77.0365), name: "White House")

// Set options
let options = NavigationRouteOptions(waypoints: [origin, destination])

// Request a route using MapboxDirections.swift
Directions.shared.calculate(options) { (waypoints, routes, error) in
guard let route = routes?.first else { return }
// Pass the generated route to the the NavigationViewController
viewController = NavigationViewController(for: route)
viewController.modalPresentationStyle = .fullScreen

}
return viewController
}

func updateUIViewController(_ uiViewController: NavigationViewController, context: Context) {

}
}

Blank Map with Mapbox and SwiftUI

You need to set your MGLMapboxAccessToken in Info.plist.

SwiftUI + MapBox integration messes up navbar

Updating Xcode from 11.3.1 to 11.4.1 did the trick.

Mapbox + SwiftUI: UI Refresh not propagating

Answering my own question here thanks to this post

https://github.com/mapbox/mapbox-maps-swiftui-demo/issues/3#issuecomment-623905509

In order for this to work it is necessary to update the UIView being rendered inside Mapview:

func updateUIView(_ uiView: MGLMapView, context: Context) {
updateAnnotations(uiView)
trackUser()
}

private func updateAnnotations(_ view: MGLMapView) {
if let currentAnnotations = view.annotations {
view.removeAnnotations(currentAnnotations)
}
view.addAnnotations(annotations)
}


Related Topics



Leave a reply



Submit