MKLaunchOptionsMapSpanKey & Apple MapKit - swift

What is the correct way to auto zoom an iOS MapKit MKMapItem generated map when it first displays using the option MKLaunchOptionsMapSpanKey:?
Specifically, how should the zoom factor be entered for MKLaunchOptionsMapSpanKey:??? (i.e. MKLaunchOptionsMapSpanKey:0.1).
Or, alternatively, is there another way programmatically to auto zoom the map when it first displays which I am not aware of?
#IBAction func getDirections(sender: AnyObject) {
let mapItem = MKMapItem.mapItemForCurrentLocation()
let coords = CLLocationCoordinate2DMake(latitude, longitude)
mapItem.name = "User Location"
let options = [MKLaunchOptionsMapSpanKey:???,MKLaunchOptionsMapCenterKey:location, ]
let place = MKPlacemark(coordinate: coords, addressDictionary:nil)
mapItem.openInMapsWithLaunchOptions(options)
}

Related

Problem with reverse geocoder and passing data between view controllers Xcode

I have a mapView in one view controller with an MKPointAnnotation. I've applied reverse Geocoder to get the street name from the coordinates and I'm trying to take that street name onto another view controller and place it into a label. But that label from the second view controller always shows the coordinates 0.0, instead of the street name.
func configureAddressNameTry() {
let vc = ViewController()
let lat = vc.annotation.coordinate.latitude
let long = vc.annotation.coordinate.longitude
let geocoder = CLGeocoder()
geocoder.reverseGeocodeLocation(CLLocation(latitude: lat, longitude: long)) { (placemarks, error) in
if let places = placemarks {
for place in places {
// This is the line that gives me the coordinates 0.0 (North Atlantic Ocean)
self.addressNameTry.text = place.name
}
}
}
I think I have all the necessary code for the user location and the information in the info.plist, so I don't know what I'm missing. I'm new to programming and I hope I'm not making a basic error.
Thank you for your replies :)

annotation Display Priority doesn't do what I expect, how to keep custom pin on screen

I use the code below on view did load to add a custom annotation icon for the map center that the user started at so that if they scroll away they can always see their starting point.
if let lat = curBlip.blip_lat, let lon = curBlip.blip_lon {
let mapCenter = CLLocationCoordinate2DMake(lat, lon)
let mapSpan = MKCoordinateSpanMake(0.01, 0.01)
let mapRegion = MKCoordinateRegionMake(mapCenter, mapSpan)
self.map.setRegion(mapRegion, animated: true)
let coordinate = CLLocationCoordinate2D(latitude: lat, longitude: lon)
let annotation = MKPointAnnotation()
annotation.coordinate = coordinate
annotation.title = "Your Blips Location"
annotation.subtitle = "Subtitle Placeholder"
self.map.addAnnotation(annotation)
When the view loads I load that annotation so its always first and I set a bool named "set" to true after the first annotation to ensure that it gets the custom icon. The issue I am having is that even though I have the annotation set to display priority required the annotation disappears when I move the map away. How can I make that annotation always persist or is there a better way to set a "this is where the map started" circle that doesn't go away?
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
if set {
return nil
} else {
let view = MKAnnotationView(annotation: annotation, reuseIdentifier: "annotationId")
view.image = UIImage(named: "locationArea50")
view.canShowCallout = true
view.displayPriority = .required
set = true
return view
}
Then after I scroll the map away a little bit, I suspect scrolling far enough that the system has to make them reappear the annotation disappears. I assume this has to do with how the grouping of annotations works but that blue annotation is special and I want it to always be present, which is what I thought displayPriority did.
The default value of displayPriority is .required .
So for correct overlapping you need to downgrade priority of red annotations:
redAnnotation.displayPriority = .defaultHigh

How to make a custom iconView in google maps with swift?

I need to do something like this
a marker with a static label in google maps sdk for iOS
If there is gonna be a lot of markers, I do not recommend using iconView because it makes UI so laggy, but here it goes:
Create a UIView file as "MarkerInfoView", which will be created as MarkerInfoView.xib
Then design your UI in there, add your imageView for your icon, then add other necessary views to complete your iconView. Also include marker in the design as an imageView. Because Im not 100% sure but I think you cant use both iconView and icon in google maps.
Then create a swift file called "MarkerInfoView.swift", go to MarkerInfoView.xib and select it's class as MarkerInfoView.
Then create another swift file, lets call it PlaceMarker, inside that file you will create a class which will conform to GMSMarker, then you will initialize your view to set it equal to iconView in PlaceMarker class. Lets do it as following:
class PlaceMarker: GMSMarker {
//Initialize with lat and long, then set position equal to the coordinate.
// 'position' comes from inheriting from GMSMarker, which is google marker.
init(latitude: Double, longitude: Double, distance: Double, placeName: String) {
super.init()
if let lat: CLLocationDegrees = latitude,
let long: CLLocationDegrees = longitude {
let coordinate = CLLocationCoordinate2D(latitude: lat, longitude: long)
position = coordinate
}
let view = Bundle.main.loadNibNamed("MarkerInfoView", owner: nil, options: nil)?.first as! MarkerInfoView
// you can set your view's properties here with data you are sending in initializer.
// Remember if you need to pass more than just latitude and longitude, you need
// to update initializer.
// lets say you created 2 outlet as placeNameLabel, and distanceLabel, you can set
// them like following:
view.placeNameLabel.text = placeName
view.distanceLabel.text = distance
// Once your view is ready set iconView property coming from inheriting to
// your view as following:
iconView = view
appearAnimation = .pop //not necessarily but looks nice.
}
}
Then when you have your data and your googlemaps view in a ViewController you can set like:
let latitude = 101.432432 //arbitrary, should come from your source
let longitude = 34.432124
let distance = 4
let placeName = "My place".
let marker = PlaceMarker(latitude: latitude, longitude: longitude, distance: distance, placeName: placeName)
marker.map = self.mapView // your google maps set your marker's map to it.

Google maps on Swift 4

Im building an app with google maps, and i would like to show a route between 2 static points
I was folling this tutorial but i can't make it yet, for some reason it dont show the route.
I dont want to make an dinamic route i just want it from two point that i´ve define
here's some code
GMSServices.provideAPIKey("MY API KEY")
let camera = GMSCameraPosition.camera(withLatitude: 19.0660043, longitude: -98.12050499999998, zoom: 18.0)
mapView = GMSMapView.map(withFrame: CGRect.zero, camera: camera)
view = mapView
var source = CLLocationCoordinate2DMake(19.060914, -98.125935)
var destination = CLLocationCoordinate2DMake(19.1660043, -98.13000)
plx help
You need to create a path first and then use that path to create a polyline
let path = GMSMutablePath()
path.add(source)
path.add(destination)
let polyline = GMSPolyline(path: path)
polyline.strokeColor = UIColor.red
polyline.strokeWidth = 3.0
polyline.map = self.map

Display current location without using CLLocationManager

I am new to iOS and I have a question about finding the current user location. I am reading in Apple documentation:
Displaying the User’s Current Location on the Map Map Kit includes
built-in support for displaying the user’s current location on the
map. To show this location, set the showsUserLocation property of your
map view object to YES. Doing so causes the map view to use Core
Location to find the user’s location and add an annotation of type
MKUserLocation to the map.
The addition of the MKUserLocation annotation object to the map is
reported by the delegate in the same way that custom annotations are.
If you want to associate a custom annotation view with the user’s
location, you should return that view from your delegate object’s
mapView:viewForAnnotation: method. If you want to use the default
annotation view, return nil from that method. To learn more about
adding annotations to a map, see Annotating Maps.
And it sounds great. But then...
import UIKit
import MapKit
class ViewController: UIViewController {
#IBOutlet weak var mapView: MKMapView!
override func viewDidLoad() {
super.viewDidLoad()
//set initial location in Honolulu
//let initialLocation = CLLocation(latitude: 21.282778, longitude: -157.829444)
mapView.showsUserLocation = true
let initialLocation = mapView.userLocation.location
centerMapOnLocation(initialLocation)
// let artwork = Artwork(title: "King David Kalakaua", locationName: "Waikiki Gateway Park", discipline: "Sculpture", coordinate: CLLocationCoordinate2D(latitude: 21.283921, longitude: -157.831661))
// mapView.addAnnotation(artwork)
//
// mapView.delegate = self
}
let regionRadius: CLLocationDistance = 1000
func centerMapOnLocation(location: CLLocation){
let coordinateRegion = MKCoordinateRegionMakeWithDistance(location.coordinate, regionRadius * 2.0, regionRadius * 2.0)
mapView.setRegion(coordinateRegion,animated:true)
}
}
And I have a fatal error: unexpectedly found nil while unwrapping an Optional value. I don't get why. If I set the location manually - of course it is fine. But in the documentation it is written that it will add an annotation on the map. No annotation is added and it crashes. Isn't it possible to get the user coordinates without using the CLLocationManager?
Have you asked permissions to the user to let your app use the location services? The docs at Apple can help you with this. Look at the sample code below to get you started:
private func beginLocationUpdates() {
// Request location access permission
_locationManager!.requestWhenInUseAuthorization()
// Start observing location
_locationManager!.startUpdatingLocation()
}