Categories
Swift Development

Maps on SwiftUI and macOS Big Sur

Im writing this little post like a reference for my self but if anyone else found it useful thats great suggestions are also Wellcome

So a little bit of context im rewriting my app from SwiftUI to SwiftUI 2 to use the new Multiplatform Apps I was using the UIViewRepresentable but I read a little about the new Map on Pauls post an want to give it a look sadly the example was very symple

So this is what I learned for the Apple Documentation an few hours of googling

Get user Location

To get the user location im gonna use this LocationFetcher class im learned from #100daysofswiftui but I had to do some twits to make it work on macOS

import CoreLocation

class LocationFetcher: NSObject, CLLocationManagerDelegate {
    let manager = CLLocationManager()
    var lastKnownLocation: CLLocationCoordinate2D?

    override init() {
        super.init()
        manager.delegate = self
    }

    func start() {
        //manager.requestWhenInUseAuthorization()
        manager.startUpdatingLocation()
    }
    func locationManager(_ manager: CLLocationManager,
                            didChangeAuthorization status: CLAuthorizationStatus) {
         
        let location = manager.location?.coordinate
        lastKnownLocation = location
    
    }
    
    func locationManager(_ manager: CLLocationManager,
                                didFailWithError error: Error) {
            print( "location manager failed with error \(error)" )
        }
}

So the first thing you can notice is manager.requestWhenInUseAuthorization() is commented this is because Macs apps make the request on startUpdatingLocation() but make it work you have to go to the Signing & Capabilities of you macOS target and on the AppSandBox check location

Making the MapView

Make the map its really easy just like this

@State private var region = MKCoordinateRegion(center: CLLocationCoordinate2D(latitude: 51.507222, longitude: -0.1275), span: MKCoordinateSpan(latitudeDelta: 0.5, longitudeDelta: 0.5))

    var body: some View {
        Map(coordinateRegion: $region)
    }

Now you can add more configurations like show the user location userTrackingMode: $trackingMode with showsUserLocation: true and allow user interactions interactionModes:.all

@State private var trackingMode = MapUserTrackingMode.follow

Map(coordinateRegion: $region, interactionModes:.all, showsUserLocation: true, userTrackingMode: $trackingMode)

But the best for me is how easy you can show MapAnnotations

Show MapAnnotation

To do this just need a collection of data that conforms to Identifiable annotationItems: collection and have a coordinate property best of all I can use my CoreData model to do this

Just had to make it conforms to Identifiable

extension User: Identifiable { }

also I added the coordinate property

public var coordinate : CLLocationCoordinate2D {
        let latitude = CLLocationDegrees(wrappedMap_cor_lat) ?? 41.158906
        let longitude = CLLocationDegrees(wrappedMap_cor_log) ??  -74.255084
        return CLLocationCoordinate2D(latitude: latitude, longitude: longitude)
    }

you can call it the way you like it

Next its just crearte a view for your annotation can be anything just a SwiftUI view

MapAnnotation<myCuztomView Market> in

So now this is how the Map look in code

 Map(coordinateRegion: $region, interactionModes:.all, showsUserLocation: true, userTrackingMode: $trackingMode, annotationItems: users){ (user) -> MapAnnotation<myCuztomView Market> in
MapAnnotation(coordinate: user.coordinate, content: {
                    myCuztomView Market(user: user)
                })
}

For more info check this links

https://developer.apple.com/documentation/mapkit/map

https://www.hackingwithswift.com/quick-start/swiftui/how-to-show-a-map-view

https://www.hackingwithswift.com/100/swiftui/78

https://stackoverflow.com/a/58882383/7195689

2 replies on “Maps on SwiftUI and macOS Big Sur”

Responder a Misael Landeros Cancelar respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *