Issue with SegmentedControl in Chapter 6


#1

I add the below code as stated in the book. On addTarget I am getting a Warning on action: “mapTypeChanged:” that is crashing the application. "No method declared with Objective-C selector ‘mapTypeChange:’. I have looked over it a couple times and tried taking the auto fix advice but i can’t seem to get past this warning.

warning segmentedControl.addTarget(self, action: “mapTypeChanged:”, forControlEvents: .ValueChanged)

    func mapTypeChanged(segControl: UISegmentedControl) {
        switch segControl.selectedSegmentIndex {
        case 0:
            mapView.mapType = .Standard
        case 1:
            mapView.mapType = .Hybrid
        case 2:
            mapView.mapType = .Satellite
        default:
           break
            
        }
    }

#2

That should be action:#selector(mapTypeChanged(_:))


#3

I had this:
segmentedControl.addTarget(self, action: “mapTypeChanged:”, forControlEvents: .ValueChanged)
Now I made the change to this:
segmentedControl.addTarget(self, action:#selector(mapTypeChanged(_:), forControlEvents: .ValueChanged))
Its still throwing an error. Says “Consecutive statements on a line must be separated by a ;”

Thanks for the help,
Nathan


#4

The #selector is missing the closing parenthesis.


#5

Ok, changed the line to this:
segmentedControl.addTarget(self, action:#selector(mapTypeChanged(_:)), forControlEvents: .ValueChanged)

Now I am getting an error: Argument of ‘#selector’ refers to a method that is not exposed to objective c. I had to move the func above this statement to get this error otherwise it didn’t know it existed.

If I leave the func below this statement I get "Use of local variable ‘mapTypeChanged’ before its declaration. Having the func below this statement is how the book has it.


#6

Digging on your forums found a topic on the same issue:

Problem with the code on Page No 105 (Programmatic Controls)

There is a statement here I found interesting:
“You shouldn’t wirte the “func mapTypeChanged(segControl: UISegmentedControl)…” in the loadView(). You should take it out of the loadView(). Then the issue is solved.”

The book has it in the load view. I am going to test this when I get home but figured I would go ahead and get in the discussion.


#7

Tested, it was do to it being within the loadView() Once I moved it out the code worked.

Thanks,
Nathan


#8

Swift 4.1 I had to do the following in loadview()

segmentedControl.addTarget(self, action: #selector(mapTypeChanged(segControl:)), for: .valueChanged)

Outside of loadview()

@objc func mapTypeChanged(segControl: UISegmentedControl) {
    switch segControl.selectedSegmentIndex {
    case 0:
        mapView.mapType = .standard
    case 1:
        mapView.mapType = .hybrid
    case 2:
        mapView.mapType = .satellite
    default:
        break
    }
}

#9

Hi @tyfrth, I was having a similar problem to you, I believe. I was getting an error about the instance method ‘mapTypeChanged’ not being exposed to Objective-C. Could you tell me the reasoning behind why you did the things you did to make this work? I’m trying to understand what’s going on here.


#10

Helpful information on #selector

As it turns out, “Selectors are a feature of Objective-C and can only be used with methods that are exposed to the dynamic Obj-C runtime. You can’t have a selector to a pure Swift method.”


#11

Yep, exactly! Thanks for the link :+1: