Reputation: 99
I'm trying to add a search feature into my map like in the apple maps app, where the search bar appears from the bottom of the view, or like an app such as uber, where the search bar is fixed on the view - any way to allow the user to search for a location in the map feature of my app.
However, I am trying to complete the app programmatically in swift, not using storyboards.
I'm sure the fix is relatively simple, such as mapView.addSubview(searchBar) but I cannot find the correct syntax. I have tried searching for an answer for a few days now, but can only find storyboard tutorials.
When I've found out how to add the search bar I'm guessing it's just a case of referencing the user search query in MKLocalSearchRequest as a naturalLanguageRequest.
As I have not been able to come close to solving this problem, there is no sample code. If anyone could provide sample code for adding this feature into my map it would be much appreciated!
class MapViewController: UIViewController, MKMapViewDelegate, CLLocationManagerDelegate {
var mapVw: MKMapView!
let locationManager = CLLocationManager()
var regionHasBeenCentered = false
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
let location = locations[0]
if !regionHasBeenCentered {
let span: MKCoordinateSpan = MKCoordinateSpanMake(0.5, 0.5)
let userLocation: CLLocationCoordinate2D = CLLocationCoordinate2DMake(location.coordinate.latitude, location.coordinate.longitude)
let region: MKCoordinateRegion = MKCoordinateRegionMake(userLocation, span)
mapVw.setRegion(region, animated: true)
regionHasBeenCentered = true //set region centred to true - map will not update loction constantly, which would effetively lock the location in place nad not allow scrolling, so once the user location updated the first time, it is set and the map can be moved
}
self.mapVw.showsUserLocation = true
}
override func viewDidLoad() {
super.viewDidLoad()
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.requestAlwaysAuthorization()
locationManager.requestWhenInUseAuthorization()
locationManager.startUpdatingLocation()
setupMapView()
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
}
func setupMapView() {
mapVw = MKMapView()
mapVw.delegate = self
let leftMargin:CGFloat = 0
let topMargin:CGFloat = 0
let mapWidth:CGFloat = view.frame.size.width
let mapHeight:CGFloat = view.frame.size.height
mapVw.frame = CGRect(x: leftMargin, y: topMargin, width: mapWidth, height: mapHeight)
let noLocation = self.mapVw.userLocation.coordinate
let span:MKCoordinateSpan = MKCoordinateSpanMake(0.05, 0.05)
let pinLocation = MKCoordinateRegionMake(noLocation, span)
mapVw.setRegion(pinLocation, animated: true)
print(pinLocation)
print(noLocation)
//setup long press gesture
let longPress = UILongPressGestureRecognizer(target: self, action: #selector(self.addAnnotation(_:)))
self.mapVw.addGestureRecognizer(longPress)
view.addSubview(mapVw)
}
//add annotation
@objc func addAnnotation(_ gestureRecognizer:UIGestureRecognizer) {
if gestureRecognizer.state != UIGestureRecognizerState.began {
return
}
let touchPoint = gestureRecognizer.location(in: self.mapVw)
let newCoordinates = self.mapVw.convert(touchPoint, toCoordinateFrom: self.mapVw)
let annotation = MKPointAnnotation()
annotation.coordinate = newCoordinates
annotation.title = "Virtual Location"
annotation.subtitle = "Dropped Pin"
self.mapVw.removeAnnotations(mapVw.annotations)//remove previous pin
self.mapVw.removeAnnotation(annotation)
//create circle attributes
let cent = newCoordinates
let rad: Double = 500
let circle = MKCircle(center: cent, radius: rad)
self.mapVw.addAnnotation(annotation)
self.mapVw.removeOverlays(self.mapVw.overlays)//remove previous circle
self.mapVw.add(circle)
print(newCoordinates)
print(circle)
}
//circle overlay function
func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
if overlay.isKind(of: MKCircle.self){
let circleRenderer = MKCircleRenderer(overlay: overlay)
circleRenderer.fillColor = UIColor.blue.withAlphaComponent(0.05)
circleRenderer.strokeColor = UIColor.blue
circleRenderer.lineWidth = 0.5
return circleRenderer
}
self.mapVw.removeOverlays(overlay as! [MKCircle])
print(overlay)
return MKOverlayRenderer(overlay: overlay)
}
}
Upvotes: 0
Views: 1203
Reputation: 7451
Is this the kind of thing that you wanted to do?
let mySearchBar = UISearchBar()
mySearchBar.frame = CGRect(x: 0, y: view.frame.size.height - 50, width: view.frame.size.width, height: 50)
mySearchBar.showsCancelButton = true
mySearchBar.placeholder = "sample"
self.view.addSubview(mySearchBar)
Upvotes: 1