提问人:Pekka 提问时间:7/30/2016 最后编辑:CommunityPekka 更新时间:4/18/2017 访问量:5517
添加 UIButton 目标时出现“classname has no member functionname”
"classname has no member functionname" when adding UIButton target
问:
这里是 Swift 和 iOS 开发的超级新手。
我正在阅读有关在单个视图 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 👍")
}
但是当我编译时,它抱怨:
类型“RatingControl”没有成员“ratingButtonTapped”
我已经 100% 确定该函数存在,在类中,并且已正确命名。完整来源
我是否遗漏了什么?
我试过什么:
根据这个答案添加到类定义中(但对于仅限 Swift 的东西来说,这似乎很奇怪,不是吗?
@objc
明确提出(但看起来没有必要)
ratingButtonTapped()
public
摆弄字符串而不是选择器等等,但这只会在以后崩溃。
button.addTarget(self, action: "RatingControl.ratingButtonTapped", for: .touchDown)
答:
发生这种情况是因为 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 运行时可见的函数。大多数时候,您都可以免费获得它,因为您是在最终继承自 (like ) 的类中实现的。如果你有一个仅 Swift 的类,它不继承自 ,那么你可以添加以使类和方法对 Objective-C 运行时可见。NSObject
UIViewController
NSObject
@objc
在 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)
评论
如果要从其他类调用视图控制器中的操作,可以尝试此操作。
将 ViewController() 用于目标。将 ViewController.functionName 用于选择器。不要对视图控制器变量使用帮助程序方法,如“vc”,否则您将无法访问 ViewController 中的对象。
下面是一个示例目标:
self.addTarget(ViewController(), action:#selector(ViewController.Test(_:)), for: UIControlEvents.touchDragInside)
在视图控制器中,下面是一个示例操作
@IBAction func Test(_ sender: Any?) {
print("Goodtime was here")
}
在目标中,必须添加 (),但不能在操作的选择器中添加。您不必调用@IBAction,它可以是func。有些人使用@objc或公共,这些前缀中的任何一个在操作上都应该有效。
查看时,如果操作位于不同的 Class 或 ViewController 中,则必须将 Class 引用放在目标和操作的选择器中。否则,它将尝试始终调用同一文件中的操作,而不管它在选择器中是否正确。同样,如果操作位于同一文件使用中,则 self 用于目标和操作的选择器。
干杯
在 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!")
}
// ...
}
评论
RatingControl.ratingButtonTapped
swift3
self.methodName
ClassName.methodName