IOS lazy var UIBarButtonItem target problem

I found that this problem with UIBarButtonItem is set unconsciously when using lazy var initialization.

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) } } 

Sealed results showed that barButtonItem1.target was zero, and barButtonItem2.target was itself, which seems crazy! I got this problem when I use barButtonItem1 lazy var writing, and then I found that the action of barButtonItem1 can never be called, and finally the problem was in barButtonItem1.target was null.

I do not know why this is happening, but I am sure that this is a mistake. Does anyone know something about this? I will be very grateful if you can explain about this.

+5
source share
1 answer

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?) { // call the initializer provided by UIKit self.init(barButtonSystemItem: systemItem, target: targetViewController, action: action) } } 

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

+3
source

All Articles