How to view Apple Maps in a globe using Swift? - ios

Looking for a solution I stumbled upon this post:
How to display entire globe in MKMapView
I followed the steps from Tushar Katyal but could not see a GLOBE. At least not in the simulator view. How should I apply this to be able to see a globe?
I already have a 2D view, and with a pin that resembles a range, and want to project it on a globe to be more accurate.
The code applied is this:
Function in viewDidLoad:
updateMapToShowGlobe(location: mapView.centerCoordinate)
declared function:
// MARK: Snippet to show full globe in 3d view
private func updateMapToShowGlobe(location :CLLocationCoordinate2D) {
let span = MKCoordinateSpanMake(130, 130)
let region = MKCoordinateRegionMake(location, span)
if( region.center.latitude > -90 && region.center.latitude < 90 && region.center.longitude > -180 && region.center.longitude < 180 ){
mapView.setRegion(region, animated: true)
}
}
I need to have a "world view" for some results, and a closer view zooming in but also on the globe, since I have to center pins in very northern locations.

Related

Change MKMapView's Zoom - Swift 4

I using Apple's MapKit and MKMapView to show a location on screen. The function I am using is:
func displayLocation() {
locationMap.setRegion(MKCoordinateRegion(center: CLLocationCoordinate2DMake(userConnected.siteConnectedLat!, userConnected.siteConnectedLong!), span: MKCoordinateSpanMake(0.05, 0.05)), animated: true)
let locationPin = CLLocationCoordinate2D(latitude: userConnected.siteConnectedLat!, longitude: userConnected.siteConnectedLong!)
let annotation = MKPointAnnotation()
annotation.coordinate = locationPin
locationMap.addAnnotation(annotation)
locationMap.showAnnotations([annotation], animated: true)
}
Is is then called in the viewDidLoad method of the View Controller. Apple's documentation says that the span should change the zoom but even changing the span is putting minimum effect on the map. I want it to be zoomed out enough so that we can clearly see like 3-4 European countries, i.e, a significant amount of zoom-out.
This is what my map looks like in simulator:
This is how it looks like after I press enlarge:
You need to set the region of the map in viewDidAppear, not viewDidLoad. When viewDidLoad is called, the map view has just been loaded - the map hasn't been rendered yet, so you can't set its region.
Another thing to change is the span. (0.05, 0.05) seems too small a span to show 3-4 countries. You should try something bigger, like (5, 5). Remember that these numbers represent in degrees the width and height of the map region.

How to display entire globe in MKMapView

I am working on a map app and I want to enable user to zoom out to entire globe. I am using MKMapView. I saw that this feature is available in iOS map app.
Can anyone tell how can I achieve the same in my app.
All you need to do is either
(Since iOS 12, November 2018 at least)
mapView.mapType = .satelliteFlyover
or
mapView.mapType = .hybridFlyover
That's all.
I hope you find it useful.
Change the map to Hybrid Flyover or Satellite Flyover
and Enable 3D View from storyboard
Call this function from viewDidLoad
updateMapToShowGlobe(location: mapView.centerCoordinate)
// MARK: Snippet to show full globe in 3d view
private func updateMapToShowGlobe(location :CLLocationCoordinate2D) {
let span = MKCoordinateSpanMake(130, 130)
let region = MKCoordinateRegionMake(location, span)
if( region.center.latitude > -90 && region.center.latitude < 90 && region.center.longitude > -180 && region.center.longitude < 180 ){
mapView.setRegion(region, animated: true)
}
}
According to one of Apple's technical support staff, it appears that this view is not accessible using MapKit:
This view is not available through MapKit.
https://forums.developer.apple.com/thread/101479

Swift mkmapview get zoom level, width or radius of visible map area from latitude longitude delta

I am in a confusion, on how to get a zoom level and radius of a visible area of the map (using mapkit mapview).
Here is what I am looking for (either of them or both, as needed) -
Zoom level, is to see at what level of the map is being shown to the users and with that information, I want to display the custom pins in the visible area. If zoom level is high, I need to show the actual logos of some commerce stores as pins. If zoom level is low, I need to show colored dots instead of logos.
As of now, I am using let updatedRadius = (mapView.camera.altitude)/1000 to get altitude of the camera, and if the updatedRadius value is > 25.0, I am showing colored dots. Below 25.0, I show the logos. I am doing this in regionDidChanged
Is this approach correct?
Radius, is to send it as a parameter to my REST API to fetch the list of places within that radius. When user zooms out on the map, visible area increases and so the REST API needs bigger radius to return the places covered in that area.
Ultimately, what should happen is, whenever user zooms out, then the radius changes. I need to send this changed radius to my REST to get an updated list.
What are latitude longtitude deltas, can we get radius/width of visible area using these values?
let latitudeDeltaVal = mapView.region.span.latitudeDelta
let longitudeDeltaVal = mapView.region.span.longitudeDelta
Can someone throw some light on what needs to be done please?
Since you need to call the api when the region changes you need to calculate the radius in mapView's delegate function, RegionDidChange.
func mapView(mapView: MKMapView, regionDidChangeAnimated animated: Bool) {
let centralLocation = CLLocation(latitude: mapView.centerCoordinate.latitude, longitude: mapView.centerCoordinate.longitude)
self.centralLocationCoordinate = mapView.centerCoordinate
print("Radius - \(self.getRadius(centralLocation))")
}
func getRadius(centralLocation: CLLocation) -> Double{
let topCentralLat:Double = centralLocation.coordinate.latitude - mapView.region.span.latitudeDelta/2
let topCentralLocation = CLLocation(latitude: topCentralLat, longitude: centralLocation.coordinate.longitude)
let radius = centralLocation.distanceFromLocation(topCentralLocation)
return radius / 1000.0 // to convert radius to meters
}
To account for both landscape and portrait orientations, and/or situations where the map orientation is close to Northeast, Northwest, Southwest, Southeast, and to enclose the full screen up to the corners, one should consider both latitudeDelta and longitudeDelta:
func getRadius() -> Double{
let centralLocation = CLLocation(latitude: mapView.region.center.latitude, longitude: mapView.region.center.longitude)
let cornerOfMap = CLLocation(latitude: centralLocation.coordinate.latitude + mapView.region.span.latitudeDelta , longitude: centralLocation.coordinate.longitude + mapView.region.span.longitudeDelta)
let radius = centralLocation.distance(from: cornerOfMap)
return radius / 1000.0 // to convert radius to meters
}

User Current Location on specific position on MAP

MKMapView
CoreLocation
Swift3.0
I have a requirement like this:
Creating an application in which I am getting Lat and Long for various location from webservice . Ploting these locations on map with Custom AnnotationView . Apart from this, I'm showing User Current Location with Custom Image.
Here everything working fine.
Now, when user moves then User Current Location Pin changes its position so there is an important requirement for this, I need to make this Current Location position in such a way that it stick in the bottom of map (just 100 pixel) above from bottom.
I did Some RND and find out few useful links:
Centering MKMapView on spot N-pixels below pin
How can I center my mapview so that the selected pin is not in the middle of the map but in 1/3 of it?
set current location icon lower side in MKMapView
But this not working anymore.
Kindly suggest how can I set user Current Location pin in iOS map in such a way that it always at the bottom of Map (100 pixel above from Bottom)
Required Pin position:
Currently it is showing in other position.
Note - **Dont want Google Map for such functionality.
If you have been using something like this mapView.setUserTrackingMode(.Follow, animated: true) then user location will be always displayed in the center of the map, zoom/pan will be automatically adjusted whenever user location is updated.
You need to disable the UserTrackingMode and then manually adjust the map zoom/pan using func setVisibleMapRect(_ mapRect: MKMapRect, edgePadding insets: UIEdgeInsets, animated animate: Bool) each time whenever user location is changed.
I used following code in similar situation
let annotationPoint = MKMapPointForCoordinate(mapView.userLocation.coordinate);
var zoomRect = MKMapRectMake(annotationPoint.x, annotationPoint.y, 1, 1);
annotationPoint = MKMapPointForCoordinate(annotation.coordinate);
let pointRect = MKMapRectMake(annotationPoint.x, annotationPoint.y, 1, 1);
zoomRect = MKMapRectUnion(zoomRect, pointRect);
mapView.setVisibleMapRect(zoomRect, edgePadding: UIEdgeInsetsMake(40, 50, 160, 50), animated: true)
p.s. edgePadding is your friend in this case.
Here is the trick to use to position the map in such a way that UserLocation pin gets adjusted automatically :
func setUserLocationOnLowerPositiononMap(coordinate: CLLocationCoordinate2D) {
var region = MKCoordinateRegion(center: coordinate, span: MKCoordinateSpan(latitudeDelta: 0.01, longitudeDelta: 0.01))
region.center = coordinate
self.map.setRegion(region, animated: true)
//self.map.moveCenterByOffSet(offSet: CGPoint(x: 0, y: -130), coordinate: coordinate)
self.map.moveCenterByOffSet(offSet: CGPoint(x: 0, y: SCREEN_HEIGHT - SCREEN_HEIGHT * 4/3 + 0 ), coordinate: coordinate)
}

How to zoom in or out a MKMapView in Swift?

Objective
I need my app to zoom in or out a MKMapView.
Code
I thought of animating the value of the altitude of a MKMapCamera. Though, this doesn't zoom in or out the map.
let mapCamera = MKMapCamera()
mapCamera.altitude = 1000000
mapView.camera = mapCamera
UIView.animateWithDuration(10, delay: 0., options: UIViewAnimationOptions.CurveLinear, animations: {
mapCamera.altitude = 6000000
}, completion: {(finished: Bool) in
})
mapView.camera = mapCamera
Question
How do I zoom in or out a MKMapView? Are there any other ways to do so?
Here is an extension based on kevins answer https://stackoverflow.com/a/20129379/1488696
With it you'll be able to zoom in and out as required
extension MKMapView {
// delta is the zoom factor
// 2 will zoom out x2
// .5 will zoom in by x2
func setZoomByDelta(delta: Double, animated: Bool) {
var _region = region;
var _span = region.span;
_span.latitudeDelta *= delta;
_span.longitudeDelta *= delta;
_region.span = _span;
setRegion(_region, animated: animated)
}
}
Use it like so: myMapView.setZoomByDelta(0.5, animated: true)
MKMapCamera is used for 3D maps. So its likely not what you're looking for
Apple Docs
An MKMapCamera object describes a virtual camera that you use to define the appearance of the map. A camera object creates a virtual viewpoint above the map surface and affects how the map renders its tiles and other content. You use a camera object to specify the location of the camera on the map, the compass heading that corresponds to the camera’s viewing direction, the pitch of the camera relative to the map perpendicular, and the camera’s altitude above the map. These factors let you create a map view that is not just flat but offers a more 3D-like experience."
Use the method setRegion:animated:. It takes an MKCoordinateRegion parameter. The region includes a span, which determines the range of north-to-south latitude shown on the screen.

Resources