添加 UIButton 目标时“类名没有成员函数名”
Posted
技术标签:
【中文标题】添加 UIButton 目标时“类名没有成员函数名”【英文标题】:"classname has no member functionname" when adding UIButton target 【发布时间】:2016-07-30 11:11:37 【问题描述】:这里是 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 ????")
但是当我编译时,它会抱怨:
类型“RatingControl”没有成员“ratingButtonTapped”
我已经 100% 确定该函数存在于类中,并且命名正确。 Full source
我有什么明显的遗漏吗?
我尝试了什么:
根据 this answer 将 @objc
添加到类定义中(但这对于仅 Swift 的东西来说似乎奇怪,不是吗?)
明确地将ratingButtonTapped()
设为public
(但这看起来没有必要)
摆弄字符串而不是选择器,button.addTarget(self, action: "RatingControl.ratingButtonTapped", for: .touchDown)
等等,但这只会在以后崩溃。
【问题讨论】:
啊哈! XCode 的自动提示功能回答了这个问题:我现在需要使用RatingControl.ratingButtonTapped
,不带括号。这工作正常并且现在可以编译。我可以删除这个问题 - 但如果有人想提供更详细的答案以及为什么会发生这种情况,我们也许可以将其作为未来读者遇到相同问题的有用资源?
我认为这个问题只要标记为swift3
就可以了,因为一旦 Swift 3 成为标准,这可能会引起一些混乱。关于选择器的一个提示:如果方法与调用者在同一范围内,您可以调用self.methodName
而不是ClassName.methodName
,不过只是一个装饰细节。
【参考方案1】:
在 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)
。
【讨论】:
如果函数没有任何参数并且发生这种情况怎么办? @kashish,不清楚您的问题是什么。最好开始你自己的线程,你会得到或被引导到更合适的答案。【参考方案2】:这是因为 Swift 3 改变了它处理第一个参数名称的方式。在 Swift 3 中,调用函数时必须使用所有参数名称,除非将显式 _
声明为参数名称。
如果您将函数声明为:
func ratingButtonTapped(_ button: AnyObject)
print("Button pressed ?")
您也可以使用它作为您的选择器:
#selector(RatingControl.ratingButtonTapped(button:))
根据这个答案将@objc 添加到类定义中(但这似乎 对一个只有 Swift 的东西来说很奇怪,不是吗?)
您的代码可能在 Swift 中,但是当您为 Cocoa Touch(iOS 框架)编码时,您正在与 Objective-C 运行时进行交互。 selector 是一个需要对 Objective-C 运行时可见的函数。大多数情况下,您都可以免费获得它,因为您在一个最终继承自NSObject
的类中实现它(例如UIViewController
)。如果您有一个不继承自 NSObject
的纯 Swift 类,那么您可以添加 @objc
以使该类和方法对 Objective-C 运行时可见。
【讨论】:
【参考方案3】:如果你想从不同的类调用视图控制器中的动作,你可以试试这个。
为您的目标使用 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,它可以是函数。有些人在操作上使用 @objc 或 public 任何这些前缀都应该起作用。
查看,如果动作在不同的 Class 或 ViewController 中,则必须将 Class 引用放在目标和动作的选择器中。否则,它将尝试始终在同一个文件中调用该操作,无论它在选择器中是否正确。同样,如果动作在同一个文件中,使用 self 作为目标并在动作的选择器内。
干杯
【讨论】:
【参考方案4】:首先在 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!")
// ...
【讨论】:
以上是关于添加 UIButton 目标时“类名没有成员函数名”的主要内容,如果未能解决你的问题,请参考以下文章
将按钮超级视图控制器添加到另一个视图控制器时,UIButton 目标无法识别
在 UITableViewCell 中为 UIButton 添加和删除目标操作