Swift中的Target-Action不遵守默认参数

时间:2016-12-14 20:29:44

标签: ios swift

我有一个UIBarButtonItem,我想显示一个抽屉菜单。

我实现了一个如下所示的功能:

func showMenu(animated: Bool = true) {
     self.rootViewController.presentViewController(self.menuViewController, animated: animated, completion: nil)
}

这是在名为HomeCoordinator

的类中实现的

现在,我已经为我的UIBarButtonItem添加了一个目标和操作,如下所示:

    s.menuItem.target = self
    s.menuItem.action = #selector(HomeCoordinator.showMenu)

当通过barbuttonitem执行showMenu函数时,动画参数为false。为什么是这样?我可以在不改变功能的情况下改变它吗?

谢谢!

3 个答案:

答案 0 :(得分:2)

有两个问题。

问题A与您问题的核心有关:为什么不应用默认参数。这是因为Objective-C不支持默认参数,UIBarButtonItem是Objective-C类。它对您在Swift中分配的默认参数一无所知。如果从Swift中调用该函数,则仅注入默认参数。

问题B与Cocoa(目标)行动的签名有关。您通常可以省略参数,但是您分配给Cocoa控件的操作总是将sender作为第一个参数(负责调用操作的对象),如下所示:

func showMenu(_ sender: UIBarButtonItem) { ... }

所有操作都应遵循此签名。

所以你可能应该将两者分开:

func showMenu(animated: Bool = true) {
  self.rootViewController.presentViewController(self.menuViewController,
                                                animated: animated, 
                                                completion: nil)
}

func onShowMenu(_ sender: Any) {
  showMenu()
}

s.menuItem.target = self
s.menuItem.action = #selector(HomeCoordinator.onShowMenu)

答案 1 :(得分:1)

我认为你不能做你想做的事。 IBActions有一个特定的签名。它们要么没有参数,要么是发送者(AnyObject类型,我相信),或者是发送者和触发UIEvent。 3个签名看起来像这样:

@IBAction func doSomething()
@IBAction func doSomething(sender: UIButton)
@IBAction func doSomething(sender: UIButton, forEvent event: UIEvent)

编辑:

上面的方法签名直接从最新版本的Xcode的UIControl文档中复制。看起来他们没有为Swift 3更新。他们应该真的:

@IBAction func doSomething()
@IBAction func doSomething(_ sender: UIButton)
@IBAction func doSomething(_ sender: UIButton, forEvent event: UIEvent)

(由rmaddy指出。下划线表示发件人参数未命名。)

您正在声明一个没有参数的选择器,但您的showMenu函数有一个BOOL参数。您不能将任意对象传递给IBAction - 它必须是触发操作的发送方(A UIControl,通常是按钮。)

尝试将选择器更改为

s.menuItem.action = #selector(HomeCoordinator.showMenu(_:))

但我认为它不会起作用。

答案 2 :(得分:0)

UIBarButtonItem操作仅接受引用以UIBarButtonItem实例作为参数的方法的选择器。

func methodName(_ sender: UIBarButtonItem) {
    ...
}


#selector(ClassName.methodName(_:))

其他参数类型可能看似合法(BoolInt),但它们可能没用。