iOS lazy var UIBarButtonItem目标问题

当使用lazy var初始化时,我无意识地发现了这个UIBarButtonItem目标问题。

class ViewController: UIViewController { lazy var barButtonItem1 = UIBarButtonItem(barButtonSystemItem: .cancel, target: self, action: #selector(action1)) lazy var barButtonItem2: UIBarButtonItem = { let barButtonItem = UIBarButtonItem(barButtonSystemItem: .cancel, target: self, action: #selector(action2)) return barButtonItem } override func viewDidLoad() { super.viewDidLoad() print(barButtonItem1.target, barButtonItem2.target) } } 

打印结果显示barButtonItem1.target为零,而barButtonItem2.target为自己,这看起来很疯狂! 当我使用barButtonItem1的lazy var写入时,我得到了这个问题,然后我发现barButtonItem1的动作永远不会被调用,最后问题是barButtonItem1.target为零。

我不知道为什么会发生这种情况,但是我很确定这是一个错误。 有没有人知道这件事? 如果你能解释一下,我会非常感激。

下面的解释是我的猜测 。 不幸的是,我没有足够的声誉发表评论,所以让我给你一个答案。

我的猜测:这是一个编译器错误。


首先,我制作了一个UIBarButtonItem的小扩展。 (第二个参数不是Any?UIViewController?

 extension UIBarButtonItem { convenience init(barButtonSystemItem systemItem: UIBarButtonSystemItem, targetViewController: UIViewController?, action: Selector?) { // call the initializer provided by UIKit self.init(barButtonSystemItem: systemItem, target: targetViewController, action: action) } } 

然后我尝试用下面的代码初始化惰性存储的variables。

 class ViewController: UIViewController { lazy var barButtonItem1 = UIBarButtonItem(barButtonSystemItem: .cancel, targetViewController: self, action: #selector(action)) override func viewDidLoad() { super.viewDidLoad() print(barButtonItem1.target) } func action() { } } 

然后编译器提出错误,并说

无法将types'(NSObject) – >() – > ViewController'的值转换为期望的参数types“UIViewController?”

这表明编译器无法确定selfViewController 。 (由UIKit提供的初始化器会编译,因为第二个参数是Any?它接受types(NSObject) -> () -> ViewController

但是,当给types注释的懒惰variables

 lazy var barButtonItem1: UIBarButtonItem = UIBarButtonItem(barButtonSystemItem: .cancel, targetViewController: self, action: #selector(action)) 

源代码愉快编译和barButtonItem1.target被设置为self

我相信types注释帮助编译。 以上是我猜你遇到的问题是由编译器错误引起的。


另请参阅:有报告类似于您遇到的问题的问题。 它们都是编译器错误。

斯威夫特懒惰使用自我实例化

使用懒惰实例化时input推理

Interesting Posts