" classname没有成员函数名"添加UIButton目标时

时间:2016-07-30 11:11:38

标签: swift swift3

Swift和iOS开发中的超级新手。

我正在关注this tutorial关于在单个视图iOS应用中实现自定义控件的问题。它是一个Swift 2教程,但到目前为止,我还可以将所有内容转换为3(我使用的是XCode 8 Beta)。

我有一个自定义类RatingControl,连接到故事板中的View

在班级的构造函数中,我创建了一个按钮:

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

然后,我尝试为按钮指定一个动作。教程说我应该这样做:

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

然后在同一个RatingControl类中创建方法:

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

但是当我编译时,它会抱怨:

  

type" RatingControl"没有会员" ratingButtonTapped"

我已经100%确定该功能在课堂上,并且正确命名。 Full source

我有什么明显的遗失吗?

我尝试了什么:

  • 根据this answer@objc添加到类定义中(但对于仅限Swift的东西,似乎很奇怪,不是吗?)

    < / LI>
  • 明确制作ratingButtonTapped() public(但这看起来不应该是必要的)

  • 摆弄字符串而不是选择器,button.addTarget(self, action: "RatingControl.ratingButtonTapped", for: .touchDown)等等,但这只会在以后崩溃。

4 个答案:

答案 0 :(得分:16)

在Swift 3中,func ratingButtonTapped(button: UIButton)的方法参考变为ratingButtonTapped(button:)

因此,使用#selector(RatingControl.ratingButtonTapped(button:))也可以。

如果您想保留#selector(RatingControl.ratingButtonTapped(_:)),则需要将ratingButtonTapped方法声明为:

func ratingButtonTapped(_ button: UIButton) { //<- `_`
    print("Button pressed ")
}

如果您在课程中只有一个ratingButtonTapped方法,则可以将选择器设置为#selector(RatingControl.ratingButtonTapped)或简单地(来自RatingControl类内)#selector(ratingButtonTapped)

答案 1 :(得分:11)

这是因为 Swift 3 改变了处理第一个参数名称的方式。在 Swift 3 中,除非将明确的_声明为参数名称,否则在调用函数时必须使用所有参数名称。

如果你宣布你的功能为:

,你用作选择器的方法很好
func ratingButtonTapped(_ button: AnyObject) {
    print("Button pressed ")
}

您也可以将此作为选择器使用:

#selector(RatingControl.ratingButtonTapped(button:))
  

根据这个答案将@objc添加到类定义中(但似乎如此   对于Swift唯一的东西很奇怪,不是吗?)

您的代码可能在Swift中,但在编写 Cocoa Touch (iOS框架)时,您正在与Objective-C运行时进行交互。 选择器是一个需要对Objective-C运行时可见的函数。您大部分时间都是免费获得这个,因为您在最终继承自NSObject的类中实现了这一点(如UIViewController)。如果您只有一个不从NSObject继承的Swift类,那么您可以添加@objc以使类和方法对Objective-C运行时可见。

答案 2 :(得分:3)

如果要从不同的类调用View Controller中的操作,可以尝试此操作。

将ViewController()用于目标。使用ViewController.functionName作为选择器。不要像“vc”那样对视图控制器变量使用辅助方法,否则您将无法访问ViewController中的对象。

以下是一个示例目标:

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

在View Controller中,这是一个示例Action

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

}

在目标中,您必须添加()但不能在操作的选择器中添加。你不必调用@IBAction,它可以只是func。有些人使用@objc或public,这些前缀中的任何一个都应该有效。

检查,如果操作位于不同的Class或ViewController中,则必须将Class引用放在目标和操作的选择器中。否则,无论选择器中的操作是否正确,它都会尝试始终在同一文件中调用操作。同样,如果操作在同一个文件中,则为目标和操作选择器内部使用self。

干杯

答案 3 :(得分:2)

首先在swift 3中添加按钮目标时,您需要位于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!")
  }

  // ...

}