“classname has no member functionname” when adding

2019-01-07 22:21发布

Super newb in Swift and iOS development here.

I am following this tutorial about implementing a custom control in a single view iOS app. It's a Swift 2 tutorial, but so far I'm doing OK transposing everything to 3 as I go (I use XCode 8 Beta).

I have a custom class, RatingControl, connected to a View in the storyboard.

In the class's constructor, I create a button:

let button = UIButton(frame: CGRect(x: 0, y: 0, width: 44, height: 44))
button.backgroundColor = UIColor.red()

Then, I try to assign an action to the button. The tutorial says I should do it like so:

button.addTarget(self, action: #selector(RatingControl.ratingButtonTapped(_:)), 
for: .touchDown)       

and then create, in the same RatingControl class, the method:

func ratingButtonTapped(button: UIButton) {
  print("Button pressed                 

标签: swift swift3
4条回答
疯言疯语
2楼-- · 2019-01-07 22:50

When adding button targets in swift 3 first you need to be in class.

class SomeClass {

  // ...

  let button = UIButton()
  // configure button to taste...

  button.addTarget(self,
                   action: #selector(doSomething),
                   for: .touchUpInside)

  // ...

  @objc public func doSomething() {
    print("hello, world!")
  }

  // ...

}
查看更多
Juvenile、少年°
3楼-- · 2019-01-07 22:56

In Swift 3, method reference for: func ratingButtonTapped(button: UIButton) becomes ratingButtonTapped(button:).

So, using #selector(RatingControl.ratingButtonTapped(button:)) also work.

And if you want to keep #selector(RatingControl.ratingButtonTapped(_:)), then you need to declare the ratingButtonTapped method as:

func ratingButtonTapped(_ button: UIButton) { //<- `_`
    print("Button pressed                                                                     
查看更多
家丑人穷心不美
4楼-- · 2019-01-07 23:01

This happened because Swift 3 has changed the way it handles the first parameter name. In Swift 3, all parameter names must be used when calling a function unless an explicit _ was declared as the parameter name.

What you used as your selector was fine if you had declared your function as:

func ratingButtonTapped(_ button: AnyObject) {
    print("Button pressed                                                                     
查看更多
时光不老,我们不散
5楼-- · 2019-01-07 23:08

If you want to call an action that is in your View Controller from a Different Class you can try this.

Use ViewController() for your target. Use ViewController.functionName for your selector. Do not use a helper method for the view controller variable like "vc", otherwise you will not be able to access objects within the ViewController.

Here is an example target:

self.addTarget(ViewController(), action:#selector(ViewController.Test(_:)), for: UIControlEvents.touchDragInside)

In your View Controller, here is an example Action

@IBAction func Test(_ sender: Any?) {
    print("Goodtime was here")

}

In the target you must add () but not in the action's selector. You do not have to call @IBAction, it can just be func. Some people use @objc or public any of those prefixes on the action should work.

Review, if the action is in a different Class or ViewController, you must put the the Class reference in both the target and the action's selector. Otherwise, it will try to always call the action within the same file regardless if it is correct in the Selector. Likewise, if the action is in the same file use, self for the target and inside the action's selector.

Cheers

查看更多
登录 后发表回答