m1234 m1234 - 2 years ago 124
Swift Question

Setting target for navigation bar button

I am trying to add a left button to my navigation controllers navigation bar but I get the error:

Cannot convert value of type 'NSObject -> () -> LocationViewController' to expected argument type 'AnyObject?'.

I have looked through other SO questions and they for the most part say to set up a navigation bar button like this. Any help is much appreciated.

var leftAddBarButtonItem : UIBarButtonItem = UIBarButtonItem(title: "Cancel", style: .Plain, target: self, action: #selector(cancelButtonTapped))

My action :

func cancelButtonTapped(sender:UIButton) {
self.dismissViewControllerAnimated(true, completion: nil)

EDIT: FullView Controller Code

import UIKit
import MapKit

protocol HandleMapSearch {
func dropPinZoomIn(placemark:MKPlacemark)

class LocationViewController: UIViewController {

let locationManager = CLLocationManager()
var resultSearchController:UISearchController? = nil
var selectedPin:MKPlacemark? = nil

var leftAddBarButtonItem : UIBarButtonItem = UIBarButtonItem(title: "Cancel", style: UIBarButtonItemStyle.Plain, target: self, action: "cancelButtonTapped")

func cancelButtonTapped(sender:UIButton) {
self.dismissViewControllerAnimated(true, completion: nil)

func setLocation() {
if let selectedPin = selectedPin {
let mapItem = MKMapItem(placemark: selectedPin)
let launchOptions = [MKLaunchOptionsDirectionsModeKey : MKLaunchOptionsDirectionsModeDriving]

@IBOutlet weak var mapView: MKMapView!

override func viewDidLoad() {

self.navigationController?.navigationItem.setLeftBarButtonItem(leftAddBarButtonItem, animated: true)

locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyBest

let locationSearchTable = storyboard!.instantiateViewControllerWithIdentifier("LocationSearchTableViewController") as! LocationSearchTableViewController
resultSearchController = UISearchController(searchResultsController: locationSearchTable)
resultSearchController?.searchResultsUpdater = locationSearchTable

let searchBar = resultSearchController!.searchBar
searchBar.placeholder = "Search or Drop a Pin"
navigationItem.titleView = resultSearchController?.searchBar

resultSearchController?.hidesNavigationBarDuringPresentation = false
resultSearchController?.dimsBackgroundDuringPresentation = true
definesPresentationContext = true

locationSearchTable.mapView = mapView
locationSearchTable.handleMapSearchDelegate = self

override func didReceiveMemoryWarning() {
// Dispose of any resources that can be recreated.

// MARK: - Navigation

// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
// Get the new view controller using segue.destinationViewController.
// Pass the selected object to the new view controller.

extension LocationViewController : CLLocationManagerDelegate {
func locationManager(manager: CLLocationManager, didChangeAuthorizationStatus status: CLAuthorizationStatus) {
if status == .AuthorizedWhenInUse {

func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
if let location = locations.first {
let span = MKCoordinateSpanMake(0.01, 0.01)
let region = MKCoordinateRegion(center: location.coordinate, span: span)
mapView.setRegion(region, animated: true)

func locationManager(manager: CLLocationManager, didFailWithError error: NSError) {
print("error:: \(error)")

extension LocationViewController: HandleMapSearch {
func dropPinZoomIn(placemark:MKPlacemark){
// cache the pin
selectedPin = placemark
// clear existing pins
let annotation = MKPointAnnotation()
annotation.coordinate = placemark.coordinate
annotation.title = placemark.name
if let city = placemark.locality,
let state = placemark.administrativeArea {
annotation.subtitle = "\(city) \(state)"
let span = MKCoordinateSpanMake(0.01, 0.01)
let region = MKCoordinateRegionMake(placemark.coordinate, span)
mapView.setRegion(region, animated: true)

extension LocationViewController : MKMapViewDelegate {
func mapView(mapView: MKMapView, viewForAnnotation annotation: MKAnnotation) -> MKAnnotationView?{
if annotation is MKUserLocation {
//return nil so map view draws "blue dot" for standard user location
return nil
let reuseId = "pin"
var pinView = mapView.dequeueReusableAnnotationViewWithIdentifier(reuseId) as? MKPinAnnotationView
pinView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: reuseId)
pinView?.pinTintColor = UIColor.orangeColor()
pinView?.canShowCallout = true
let smallSquare = CGSize(width: 60, height: 60)
let button = UIButton(frame: CGRect(origin: CGPointZero, size: smallSquare))
button.setBackgroundImage(UIImage(named: "PinButton2.jpg"), forState: .Normal)
button.addTarget(self, action: #selector(LocationViewController.setLocation), forControlEvents: .TouchUpInside)
pinView?.leftCalloutAccessoryView = button
return pinView

Answer Source

I would say there is one mistake .. looks like you set your var leftAddBarButtonItem ... line out side any function ... set it in viewDidLoad and it should be work.

If you are using swift 2.2 than your action should be #selector(cancelButtonTapped(_:)) else simply use "cancelButtonTapped:" ...

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download