为什么使用 init(barButtonSystemItem, target, action) 初始化时 UIBarButtonItem 的目标设置为 nil?



此初始化项

convenience init(barButtonSystemItem systemItem: UIBarButtonSystemItem, 
      target: Any?, 
      action: Selector?)
根据文档,

接受目标,然后在返回部分中,他们解释说它实际上被设置为nil。他们为什么要这么做?

我的意思是他们真的这么做了,因为这让我抓狂,我不得不写这样的代码:

class GameViewController: UIViewController {

    let pauseItem = UIBarButtonItem(barButtonSystemItem: .pause, target: self, action: #selector(GameViewController.pauseButtonTouchUp))
    let playItem = UIBarButtonItem(barButtonSystemItem: .play, target: self, action: #selector(GameViewController.pauseButtonTouchUp))

    override func viewDidLoad() {
        super.viewDidLoad()
        self.pauseItem.target = self
        self.playItem.target = self
        . . . 
}

因为否则操作将不会被触发。为什么他们认为接受一个参数并故意忽略它是一个好主意?

编辑:这是我的错误(如下面的答案所指出的),我使用了一个nil-self来初始化对象。然而,这个问题仍然存在。因为为什么他们说目标被设置为nil而实际上不是?

target nil,因为您在控制器init之前设置了target。你应该这样写:

class GameViewController: UIViewController {
    var pauseItem: UIBarButtonItem? = nil
    var playItem: UIBarButtonItem? = nil
    override func viewDidLoad() {
        super.viewDidLoad()
        playItem = UIBarButtonItem(barButtonSystemItem: .play, target: self, action: #selector(GameViewController.pauseButtonTouchUp))
        pauseItem = UIBarButtonItem(barButtonSystemItem: .pause, target: self, action: #selector(GameViewController.pauseButtonTouchUp))
    }
}

Swift 3 (Xcode 8.3.3)

在Swift 3中,你可以通过将属性声明为lazy var而不是let来解决这个问题,但是你也必须明确属性的数据类型,而不是依赖于推断的类型,因为否则target将再次被设置为nil由于编译器的一些quirk。

This is required ----------+
                           |
                           v
lazy var pauseItem: UIBarButtonItem = UIBarButtonItem(
    barButtonSystemItem: .pause, 
    target: self, 
    action: #selector(GameViewController.pauseButtonTouchUp)
)

我不知道为什么会这样,但它确实发生了。

最新更新