这是我的代码:
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
let btn = UIButton.init(frame: CGRect(x: 100, y: 100, width: 100, height: 100));
btn.backgroundColor = UIColor.blue
btn.addTarget(self, action: #selector(testAction(_:animated:)), for: .touchDown)
view.addSubview(btn)
}
@objc func testAction(_ sender: UIButton,animated: Bool = true){
if sender.backgroundColor == UIColor.red {
sender.backgroundColor = UIColor.blue
}else{
sender.backgroundColor = UIColor.red
}
print("animated == \(animated)")
}
}
如图所示,测试项目中添加了一个按钮。该方法有默认参数,但动画参数打印为 false。谁能告诉我为什么?我将非常感激。
这是系统错误吗?我已经在很多场景中对此进行了测试。
UIButton
通过使用类似 testAction
的方法,在传递给 action:
的对象上执行传递给 target:
的选择器来调用
performSelector:withObject:
。这本质上是 Objective-C 的事情,Swift 参数的默认值在 Objective-C 中不起作用。
在 Objective-C 中,导入
func testAction(animated: Bool = true)
就好像它没有可选参数一样。标题看起来像这样:
- (void)testActionWithAnimated:(BOOL)animated;
UIButton
希望其 action
是一种采用一个参数的方法,并且将其自身(一个 UIButton
实例)作为参数传递,以指示控制事件的“发送者”。
所以这里发生的事情是,
animated
参数传递了一个指向UIButton
实例的指针,它被强制解释为BOOL
(因为Objective-C有一个相当弱的类型系统)。结果恰好是false
。
如果您使用两个参数声明
testAction
,
@objc func testAction(_ sender: UIButton, animated: Bool = true)
那么
UIButton
中的代码只提供第一个参数的实参,而第二个参数的值是未定义的(无论当时堆栈上发生了什么,都可能)。