CJ90
CJ90

Reputation: 99

how to add search function in mapKit programmatically

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

Answers (1)

Kosuke Ogawa
Kosuke Ogawa

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

Related Questions