swift - 为什么在 Swift 中通过 Selector 调用时不考虑函数的默认参数?

标签 swift objective-c-runtime

通过选择器调用的方法不遵循默认参数值。

示例

如果我连接了一个按钮来通过选择器调用函数:

func setupButton() {
    self.button.addTarget(self, action: #selector(printValue), for: .touchUpInside)
}

@objc func printValue(value:Int = 7)
{
    if value == 7 {
       print("received default")
    } else {
       print("default unused")
    }
}

当通过代码调用此方法时 "received default" 被打印出来,但是当我按下按钮并通过选择器调用方法时 "default unused" 被打印出来,因为 7未设置为值。


为什么会这样?

最佳答案

当您调用函数时,Swift 编译器会插入默认参数。
所以这是编译时的事情。

当通过选择器手动调用函数时,您使用的是 Objective-C 运行时,它不知道您的默认参数。
这是运行时的事情

此外,Objective-C 中不存在默认参数。

您可以将 Swift 默认参数视为编译时的便利。
但是一旦你运行你的代码,它们基本上就消失了。

编辑

如果您正在寻找解决方法,我建议您使用两个不同的函数,而不使用默认参数:

@objc func printValue()
{
    printValue(value: 7)
}

@objc func printValue(value:Int)
{}

这样,您就可以通过 Objective-C 运行时调用它而无需参数。 请注意,在使用 #selector 时,您需要强制转换以解决歧义:

self.button?.addTarget(self, action: #selector((printValue as () -> Void)), for: .touchUpInside)

关于swift - 为什么在 Swift 中通过 Selector 调用时不考虑函数的默认参数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57663141/

相关文章:

Objective-C:什么是惰性类?

objective-c - 实现 Objective-C 的根类需要什么?

objective-c - 什么是 class_setIvarLayout 和 class_getIvarLayout?

swift - SKTiled : specific tile position

ios - UICollectionView 和选定的 UICollectionViewCell

ios - SpriteKit 中 Sprite 之间的碰撞

objective-c - 使用 objc_msgSend 调用实例方法

ios - 在swift iOS中计算高字节和低字节?

swift - 谷歌矩阵 - 计算出发地和目的地之间的距离

Objective-C:为什么我的对象被实例化为 __NSMallocBlock__?