protocol AnimatableBehavior { @IBAction func animate() }
问题是我希望这个方法是一个IBAction,但我从XCode得到这个错误:
Only instance methods can be declared ‘IBAction’
我的问题是,你将如何实现这样的事情?
我考虑过:
>删除@IBAction,但我需要记住在每个实现的类中添加它.不是很优雅,容易出错.
>创建一个基类而不是协议,但后来我强制所有组件继承我的基类而不是他们自己选择的基类,所以它不是一个有效的选项.
还有其他想法吗?
关于协议的IBAction的想法是因为在项目中将有许多不同的开发人员实现小的UI组件,所有这些组件都具有animate方法.组件可以以编程方式或通过Interface Builder添加,并且它们总是IBAction非常方便,因为我计划从IB文件组合它们以最大程度地简化视图控制器(这显然是仅查看任务).
因此,下面提出的在控制器中添加一个只调用组件动画的方法的解决方案并不好,因为它是冗余代码并使Controller更依赖于View.
让开发人员记住在方法上添加IBAction关键字的想法是可行的,但正如我所说它容易出错(并且我的意思是会有一些遗忘),我想确保这一点总是可以从IB访问.它还增加了额外的认知负荷,因为我需要记录协议上缺少IBAction并请求实现者手动添加它.
我知道这不是在iOS和UIKit中工作的常用方式,但这就是我发布问题的原因,也许有人有另一种想法.
解决方法
@H_502_32@ 在协议中使用@IBAction没有任何意义. @IBAction只是一个关键字,当您控制从Interface Builder拖动到实际的源代码时,Interface Builder会有一个钩子.这只是对@IBAction实际上和行为的一个简单误解.
>不必将方法标记为@IBAction,以使其成为UI元素操作的目标.您使用UI元素具有的addTarget方法集以编程方式将任何方法连接到任何操作.该方法不必标记为@IBAction来执行此操作.
>无论协议是否将方法定义为@IBAction,符合协议的类都可以添加它(并且仍然符合协议.
protocol FooProtocol { func doSomething() } class ViewControllerA: UIViewController,FooProtocol { @IBAction func doSomething() { // do something } } class ViewControllerB: UIViewController,FooProtocol { func doSomething() { // do something } }
这两个视图控制器子类都符合协议,如果你打算从接口构建器连接一个动作,那么只有@IBAction才有必要!
最终,无论你想做什么,如果你认为协议中有必要使用@IBAction,我认为你采取了错误的方法.如果不了解关于你实际做什么的更多细节,很难说正确的方法是什么,但@IBAction属于协议是没有意义的.
对我来说,似乎你的协议强制执行的方法根本不应该绑定到@IBAction方法.相反,无论用户交互应该触发动画,都应该调用animate方法.例如,如果我们不讨论协议,我的建议就是这种设置:
class ViewController: UIViewController { @IBAction func buttonThatStartsAnimation { self.animate() } func animate { // code that does all the animation } }
因此,使用协议,我们应该在实际启动动画代码的方法之间采取相同的职责分离(在协议的情况下,这显然是其他一些外部类),并且animate方法应该只处理相关动画.
重要的是,作为一般规则,您不应直接从定义它们的类外部直接引用您的@IBAction方法或@IBOutlet变量.