The explanation below is my guess. And unfortunately, I do not have enough reputation to comment, so let me give you an answer.
My guess: this is a compiler error.
First, I created a small extension UIBarButtonItem. (the second parameter does not matter Any? but the UIViewController? )
extension UIBarButtonItem { convenience init(barButtonSystemItem systemItem: UIBarButtonSystemItem, targetViewController: UIViewController?, action: Selector?) {
Then I tried to initialize the lazy stored variable using the code below.
class ViewController: UIViewController { lazy var barButtonItem1 = UIBarButtonItem(barButtonSystemItem: .cancel, targetViewController: self, action: #selector(action)) override func viewDidLoad() { super.viewDidLoad() print(barButtonItem1.target) } func action() { } }
Then the compiler raised an error and said
Cannot convert value of type '(NSObject) -> () -> ViewController' to the expected argument type 'UIViewController?'
which suggests that the compiler was unable to determine that self has a ViewController value. (The initializer provided by UIKit will compile because the second parameter is Any? Which takes a value of type (NSObject) -> () -> ViewController .)
But when let's type annotate to a lazy variable like
lazy var barButtonItem1: UIBarButtonItem = UIBarButtonItem(barButtonSystemItem: .cancel, targetViewController: self, action: #selector(action))
the source code is happily compiled, and barButtonItem1.target is self .
I believe that type annotation helped compile. The above is the reason why I think the problem you are facing is caused by a compiler error.
See also: reports problems similar to the one you encountered. Both of them are enclosed as a compiler error.
Fast lazy copying using yourself
Enter output when using a lazy instance