【问题标题】:iOS lazy var UIBarButtonItem target issueiOS 惰性 var UIBarButtonItem 目标问题
【发布时间】:2017-10-06 04:15:41
【问题描述】:

我在使用惰性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为nil,barButtonItem2.target为self,看起来很疯狂! 我在使用barButtonItem1的lazy var编写时遇到了这个问题,然后我发现barButtonItem1的action永远无法调用,最后问题是barButtonItem1.target为nil。

我不知道为什么会发生这种情况,但是我很确定这是一个错误。 有人知道吗?如果您能解释一下,我将不胜感激。

【问题讨论】:

  • 我认为您的barButtonItem1 操作不正确。首先必须使用数据类型声明lazy var。其次,您只是将其值设置为常规 var。请阅读:hackingwithswift.com/example-code/language/…
  • barButtonItem1 的声明应该是正确的,根据link
  • 根据link,barButtonItem1 的声明应该是正确的。但是,我尝试了您所说的为 barButtonItem1 添加数据类型声明,它现在表现良好。我仍然不知道是什么原因造成的。
  • 无论如何感谢您的评论!
  • 你不应该这样实现栏按钮。为什么需要这种类型的声明?

标签: ios swift uibarbuttonitem lazy-evaluation target


【解决方案1】:

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

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


首先,我制作了 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)
    }
}

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

class ViewController: UIViewController {

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

    override func viewDidLoad() {
        super.viewDidLoad()
        print(barButtonItem1.target)
    }
    func action() { }
}

然后编译器提出错误并说

无法将 '(NSObject) -> () -> ViewController' 类型的值转换为 预期的参数类型“UIViewController?”

这表明编译器无法确定self 属于ViewController。 (UIKit 提供的初始化程序会编译,因为第二个参数是Any?,它接受(NSObject) -> () -> ViewController 类型的值。)

但是当给惰性变量像类型注释时

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

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

我相信类型注释有助于编译。以上是我猜您遇到的问题是由编译器错误引起的原因。


另请参阅:报告的问题与您遇到的问题类似。两者都被归结为编译器错误。

Swift lazy instantiating using self

Type inference when using lazy instantiation

【讨论】:

  • 谢谢!所以这确实是一个编译器错误,希望苹果能尽快修复它。现在,让我们添加类型注释。
猜你喜欢
  • 2018-07-08
  • 1970-01-01
  • 2023-04-06
  • 1970-01-01
  • 2017-10-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多